JCLOUDS-1300: Subnetwork fixes and reuse the TemplateOptions.networks

This commit is contained in:
Ignasi Barrera 2017-05-25 10:06:49 +02:00
parent 2ec28df21b
commit c83a08a8d6
39 changed files with 557 additions and 235 deletions

View File

@ -17,13 +17,11 @@
package org.jclouds.googlecomputeengine;
import java.io.Closeable;
import java.net.URI;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.googlecloud.config.CurrentProject;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.features.AddressApi;
import org.jclouds.googlecomputeengine.features.AggregatedListApi;
import org.jclouds.googlecomputeengine.features.BackendServiceApi;
@ -46,12 +44,10 @@ import org.jclouds.googlecomputeengine.features.SubnetworkApi;
import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi;
import org.jclouds.googlecomputeengine.features.TargetInstanceApi;
import org.jclouds.googlecomputeengine.features.TargetPoolApi;
import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi;
import org.jclouds.googlecomputeengine.features.UrlMapApi;
import org.jclouds.googlecomputeengine.features.ZoneApi;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.EndpointParam;
public interface GoogleComputeEngineApi extends Closeable {

View File

@ -22,10 +22,11 @@ import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static java.lang.String.format;
import static org.jclouds.googlecloud.internal.ListPages.concat;
import static org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName.fromRegionAndName;
import static org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet.nameFromNetworkString;
import static org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.IMAGE_PROJECTS;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@ -34,6 +35,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
@ -43,7 +45,7 @@ import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention;
import org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName;
import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.domain.AttachDisk;
@ -56,6 +58,7 @@ import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Region;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.domain.Tags;
import org.jclouds.googlecomputeengine.domain.Zone;
import org.jclouds.googlecomputeengine.features.InstanceApi;
@ -95,34 +98,32 @@ public final class GoogleComputeEngineServiceAdapter
private final Predicate<AtomicReference<Operation>> operationDone;
private final Predicate<AtomicReference<Instance>> instanceVisible;
private final Function<Map<String, ?>, String> windowsPasswordGenerator;
private final FirewallTagNamingConvention.Factory firewallTagNamingConvention;
private final List<String> imageProjects;
private final LoadingCache<URI, Optional<Image>> diskURIToImage;
private final LoadingCache<RegionAndName, Optional<Subnetwork>> subnetworksMap;
@Inject GoogleComputeEngineServiceAdapter(JustProvider justProvider, GoogleComputeEngineApi api,
Predicate<AtomicReference<Operation>> operationDone,
Predicate<AtomicReference<Instance>> instanceVisible,
Function<Map<String, ?>, String> windowsPasswordGenerator,
Resources resources,
FirewallTagNamingConvention.Factory firewallTagNamingConvention,
@Named(IMAGE_PROJECTS) String imageProjects,
LoadingCache<URI, Optional<Image>> diskURIToImage) {
@Inject
GoogleComputeEngineServiceAdapter(JustProvider justProvider, GoogleComputeEngineApi api,
Predicate<AtomicReference<Operation>> operationDone, Predicate<AtomicReference<Instance>> instanceVisible,
Function<Map<String, ?>, String> windowsPasswordGenerator, Resources resources,
@Named(IMAGE_PROJECTS) String imageProjects, LoadingCache<URI, Optional<Image>> diskURIToImage,
LoadingCache<RegionAndName, Optional<Subnetwork>> subnetworksMap) {
this.justProvider = justProvider;
this.api = api;
this.operationDone = operationDone;
this.instanceVisible = instanceVisible;
this.windowsPasswordGenerator = windowsPasswordGenerator;
this.resources = resources;
this.firewallTagNamingConvention = firewallTagNamingConvention;
this.imageProjects = Splitter.on(',').omitEmptyStrings().splitToList(imageProjects);
this.diskURIToImage = diskURIToImage;
this.subnetworksMap = subnetworksMap;
}
@Override public NodeAndInitialCredentials<Instance> createNodeWithGroupEncodedIntoName(String group, String name,
Template template) {
GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions());
checkNotNull(options.getNetworks(), "template options must specify a network");
checkNotNull(options.getNetworks(), "template options must specify a network or subnetwork");
checkNotNull(template.getHardware().getUri(), "hardware must have a URI");
checkNotNull(template.getImage().getUri(), "image URI is null");
@ -131,15 +132,19 @@ public final class GoogleComputeEngineServiceAdapter
List<AttachDisk> disks = Lists.newArrayList();
disks.add(AttachDisk.newBootDisk(template.getImage().getUri(), getDiskTypeArgument(options, zone)));
Iterator<String> networks = options.getNetworks().iterator();
URI network = URI.create(networks.next());
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";
URI network = URI.create(options.getNetworks().iterator().next());
URI subnetwork = null;
if (isSubnetwork(network)) {
String region = template.getLocation().getParent().getId();
RegionAndName subnetRef = fromRegionAndName(region, nameFromNetworkString(network.toString()));
// This must be present, since the subnet is validated and its URI
// obtained in the CreateNodesWithGroupEncodedIntoNameThenAddToSet
// strategy
Optional<Subnetwork> subnet = subnetworksMap.getUnchecked(subnetRef);
network = subnet.get().network();
subnetwork = subnet.get().selfLink();
}
Scheduling scheduling = getScheduling(options);
@ -342,4 +347,8 @@ public final class GoogleComputeEngineServiceAdapter
return Scheduling.create(onHostMaintenance, automaticRestart, options.preemptible());
}
private static boolean isSubnetwork(URI uri) {
return uri.toString().contains("/subnetworks/");
}
}

View File

@ -55,6 +55,7 @@ import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadN
import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.compute.functions.ResetWindowsPassword;
import org.jclouds.googlecomputeengine.compute.loaders.DiskURIToImage;
import org.jclouds.googlecomputeengine.compute.loaders.SubnetworkLoader;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.compute.predicates.AtomicInstanceVisible;
import org.jclouds.googlecomputeengine.compute.predicates.AtomicOperationDone;
@ -64,6 +65,7 @@ import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.implicit.FirstZone;
@ -84,6 +86,7 @@ import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
import org.jclouds.googlecomputeengine.compute.domain.internal.GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl;
import org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName;
public final class GoogleComputeEngineServiceContextModule
extends ComputeServiceAdapterContextModule<Instance, MachineType, Image, Location> {
@ -137,6 +140,9 @@ public final class GoogleComputeEngineServiceContextModule
bind(new TypeLiteral<CacheLoader<URI, Optional<Image>>>() {
}).to(DiskURIToImage.class);
bind(new TypeLiteral<CacheLoader<RegionAndName, Optional<Subnetwork>>>() {
}).to(SubnetworkLoader.class);
bindHttpApi(binder(), Resources.class);
}
@ -203,8 +209,14 @@ public final class GoogleComputeEngineServiceContextModule
@Provides
@Singleton
protected LoadingCache<URI, Optional<Image>> diskURIToImageMap(
CacheLoader<URI, Optional<Image>> in) {
protected LoadingCache<URI, Optional<Image>> diskURIToImageMap(CacheLoader<URI, Optional<Image>> in) {
return CacheBuilder.newBuilder().build(in);
}
@Provides
@Singleton
protected LoadingCache<RegionAndName, Optional<Subnetwork>> subnetworksMap(
CacheLoader<RegionAndName, Optional<Subnetwork>> in) {
return CacheBuilder.newBuilder().build(in);
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.compute.domain.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.auto.value.AutoValue;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
/**
* Helpful when looking for resources by region and name
*/
@AutoValue
public abstract class RegionAndName {
public abstract String regionId();
public abstract String name();
RegionAndName() {
}
public static RegionAndName fromSlashEncoded(String name) {
Iterable<String> parts = Splitter.on('/').split(checkNotNull(name, "name"));
checkArgument(Iterables.size(parts) == 2, "name must be in format regionId/name");
return fromRegionAndName(Iterables.get(parts, 0), Iterables.get(parts, 1));
}
public static RegionAndName fromRegionAndName(String regionId, String name) {
return new AutoValue_RegionAndName(regionId, name);
}
public String slashEncode() {
return regionId() + "/" + name();
}
}

View File

@ -16,42 +16,38 @@
*/
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.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.logging.Logger;
import com.google.common.base.Optional;
import com.google.common.cache.CacheLoader;
@Singleton
public class SubnetworkLoader extends CacheLoader<URI, Subnetwork> {
@Resource
protected Logger logger = Logger.NULL;
public class SubnetworkLoader extends CacheLoader<RegionAndName, Optional<Subnetwork>> {
private final Resources resources;
private final GoogleComputeEngineApi api;
@Inject
SubnetworkLoader(Resources resources) {
this.resources = resources;
SubnetworkLoader(GoogleComputeEngineApi api) {
this.api = api;
}
@Override
public Subnetwork load(URI key) throws ExecutionException {
public Optional<Subnetwork> load(RegionAndName key) throws ExecutionException {
try {
return resources.subnetwork(key);
} catch (Exception e) {
throw new ExecutionException(message(key, e), e);
return Optional.fromNullable(api.subnetworksInRegion(key.regionId()).get(key.name()));
} catch (Exception ex) {
throw new ExecutionException(message(key, ex), ex);
}
}
public static String message(URI key, Exception e) {
return String.format("could not find image for disk %s: %s", key.toString(), e.getMessage());
public static String message(RegionAndName key, Exception ex) {
return String.format("could not find subnet %s in region %s: %s", key.name(), key.regionId(), ex.getMessage());
}
}

View File

@ -18,14 +18,12 @@ package org.jclouds.googlecomputeengine.compute.options;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.collect.ImmutableSet;
/** Instance options specific to Google Compute Engine. */
public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
@ -35,7 +33,6 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
private List<ServiceAccount> serviceAccounts;
private String bootDiskType;
private boolean preemptible = false;
private Set<String> subnetworks;
@Override
public GoogleComputeEngineTemplateOptions clone() {
@ -138,11 +135,6 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
return serviceAccounts;
}
public Set<String> getSubnetworks() {
return subnetworks;
}
/**
* {@inheritDoc}
*/
@ -295,22 +287,6 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
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}
*/

View File

@ -19,6 +19,8 @@ package org.jclouds.googlecomputeengine.compute.strategy;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.of;
import static org.jclouds.domain.LocationScope.ZONE;
import static org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName.fromRegionAndName;
import java.util.ArrayList;
import java.util.Arrays;
@ -41,20 +43,26 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.domain.Location;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.domain.internal.RegionAndName;
import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention;
import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.Firewall.Rule;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.features.FirewallApi;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.SshKeyPairGenerator;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
@ -72,9 +80,11 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
public static final String DEFAULT_NETWORK_NAME = "default";
private final GoogleComputeEngineApi api;
private final Resources resources;
private final Predicate<AtomicReference<Operation>> operationDone;
private final FirewallTagNamingConvention.Factory firewallTagNamingConvention;
private final SshKeyPairGenerator keyGenerator;
private final LoadingCache<RegionAndName, Optional<Subnetwork>> subnetworksMap;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -87,14 +97,17 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
GroupNamingConvention.Factory namingConvention,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
GoogleComputeEngineApi api, Predicate<AtomicReference<Operation>> operationDone,
FirewallTagNamingConvention.Factory firewallTagNamingConvention, SshKeyPairGenerator keyGenerator) {
GoogleComputeEngineApi api, Resources resources, Predicate<AtomicReference<Operation>> operationDone,
FirewallTagNamingConvention.Factory firewallTagNamingConvention, SshKeyPairGenerator keyGenerator,
LoadingCache<RegionAndName, Optional<Subnetwork>> subnetworksMap) {
super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.api = api;
this.resources = resources;
this.operationDone = operationDone;
this.firewallTagNamingConvention = firewallTagNamingConvention;
this.keyGenerator = keyGenerator;
this.subnetworksMap = subnetworksMap;
}
@Override
@ -102,16 +115,13 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Template mutableTemplate = template.clone();
GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class
.cast(mutableTemplate.getOptions());
.cast(template.getOptions());
assert template.getOptions().equals(templateOptions) : "options didn't clone properly";
// Get Network
Network network = getNetwork(templateOptions.getNetworks());
// Setup Firewall rules
getOrCreateFirewalls(templateOptions, network, firewallTagNamingConvention.get(group));
templateOptions.networks(ImmutableSet.of(network.selfLink().toString()));
// Configure networking
configureNetworking(group, templateOptions, template.getLocation());
templateOptions.userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group);
// Configure the default credentials, if needed
@ -123,30 +133,48 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
}
if (templateOptions.getRunScript() != null && templateOptions.getLoginPrivateKey() == null) {
logger.warn(">> A runScript has been configured but no SSH key has been provided."
logger.warn(">> a runScript has been configured but no SSH key has been provided."
+ " Authentication will delegate to the ssh-agent");
}
return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
return super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
}
/**
* Try and find a network previously created by the user.
* Configure the networks taking into account that users may have configured
* a custom subnet or a legacy network.
*/
private Network getNetwork(Set<String> networks) {
String networkName;
if (networks == null || networks.isEmpty()){
networkName = DEFAULT_NETWORK_NAME;
}
else {
Iterator<String> iterator = networks.iterator();
networkName = nameFromNetworkString(iterator.next());
checkArgument(!iterator.hasNext(), "Error: Please specify only one network in TemplateOptions when using GCE.");
private void configureNetworking(String group, GoogleComputeEngineTemplateOptions options, Location location) {
String networkName = null;
Network network = null;
if (options.getNetworks().isEmpty()) {
networkName = DEFAULT_NETWORK_NAME;
} else {
Iterator<String> iterator = options.getNetworks().iterator();
networkName = nameFromNetworkString(iterator.next());
checkArgument(!iterator.hasNext(),
"Error: Please specify only one network/subnetwork in TemplateOptions when using GCE.");
}
Network network = api.networks().get(networkName);
String region = ZONE == location.getScope() ? location.getParent().getId() : location.getId();
Optional<Subnetwork> subnet = subnetworksMap.getUnchecked(fromRegionAndName(region, networkName));
if (subnet.isPresent()) {
network = resources.network(subnet.get().network());
options.networks(ImmutableSet.of(subnet.get().selfLink().toString()));
logger.debug(">> attaching nodes to subnet(%s) in region(%s)", subnet.get().name(), region);
} else {
logger.warn(">> subnet(%s) was not found in region(%s). Trying to find a matching legacy network...",
networkName, region);
network = api.networks().get(networkName);
options.networks(ImmutableSet.of(network.selfLink().toString()));
logger.debug(">> attaching nodes to legacy network(%s)", network.name());
}
checkArgument(network != null, "Error: no network with name %s was found", networkName);
return network;
// Setup Firewall rules
getOrCreateFirewalls(options, network, subnet, firewallTagNamingConvention.get(group));
}
/**
@ -162,7 +190,7 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
* org.jclouds.googlecomputeengine.options.FirewallOptions)
*/
private void getOrCreateFirewalls(GoogleComputeEngineTemplateOptions templateOptions, Network network,
FirewallTagNamingConvention naming) {
Optional<Subnetwork> subnet, FirewallTagNamingConvention naming) {
Set<String> tags = Sets.newLinkedHashSet(templateOptions.getTags());
@ -188,11 +216,14 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
String name = naming.name(ports);
Firewall firewall = firewallApi.get(name);
AtomicReference<Operation> operation = null;
String interiorRange = subnet.isPresent() ? subnet.get().ipCidrRange() : DEFAULT_INTERNAL_NETWORK_RANGE;
if (firewall == null) {
List<Rule> rules = ImmutableList.of(Rule.create("tcp", ports), Rule.create("udp", ports));
FirewallOptions firewallOptions = new FirewallOptions().name(name).network(network.selfLink())
.allowedRules(rules).sourceTags(templateOptions.getTags())
.sourceRanges(of(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE))
.sourceRanges(of(interiorRange, EXTERIOR_RANGE))
.targetTags(ImmutableList.of(name));
operation = Atomics.newReference(firewallApi

View File

@ -126,13 +126,11 @@ public final class GoogleComputeEngineHttpApiModule extends HttpApiModule<Google
private final GetProject api;
private final Supplier<URI> defaultEndpoint;
private final String identityName;
@Inject
UseApiToResolveProjectName(GetProject api, @Provider Supplier<URI> defaultEndpoint, ProviderMetadata metadata) {
this.api = api;
this.defaultEndpoint = defaultEndpoint;
this.identityName = metadata.getApiMetadata().getIdentityName();
}
@Override public URI apply(Credentials in) {

View File

@ -25,6 +25,7 @@ import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
/**
* Represents a network used to enable instance communication.
@ -46,8 +47,6 @@ public abstract class Network {
public abstract String name();
public abstract NetworkType type();
@Nullable public abstract String description();
/**
@ -61,26 +60,24 @@ public abstract class Network {
* If not specified, the default value is the first usable address in IPv4Range.
*/
@Nullable public abstract String gatewayIPv4();
public abstract boolean autoCreateSubnetworks();
@Nullable public abstract List<URI> subnetworks();
public abstract List<URI> subnetworks();
public static Network create(String id, Date creationTimestamp, URI selfLink, String name, String description, String rangeIPv4,
String 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);
@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, boolean autoCreateSubnetworks, List<URI> subnetworks) {
return new AutoValue_Network(id, creationTimestamp, selfLink, name, description, rangeIPv4, gatewayIPv4,
autoCreateSubnetworks, subnetworks == null ? ImmutableList.<URI> of() : ImmutableList.copyOf(subnetworks));
}
Network() {
}
public NetworkType type() {
return !Strings.isNullOrEmpty(rangeIPv4()) ? NetworkType.LegacyNetwork
: (autoCreateSubnetworks() ? NetworkType.AutoSubnetwork : NetworkType.CustomNetwork);
}
}

View File

@ -43,20 +43,11 @@ public abstract class NewInstance {
abstract List<AccessConfig> accessConfigs();
static NetworkInterface create(URI network) {
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" })
static NetworkInterface create(URI network, List<AccessConfig> 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);
@ -88,20 +79,11 @@ public abstract class NewInstance {
@Nullable public abstract Scheduling scheduling();
/** Convenience for creating a new instance with only a boot disk and minimal parameters. */
public static NewInstance create(String name, URI machineType, URI network, URI sourceImage) {
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,
@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);
@ -112,8 +94,9 @@ public abstract class NewInstance {
foundBoot = true;
}
}
return create(name, machineType, null, ImmutableList.of(NetworkInterface.create(network)), ImmutableList.copyOf(disks),
description, tags != null ? tags : Tags.create(), Metadata.create(), null, null);
return create(name, machineType, null, ImmutableList.of(NetworkInterface.create(network, subnetwork)),
ImmutableList.copyOf(disks), description, tags != null ? tags : Tags.create(), Metadata.create(), null,
null);
}
@SerializedNames({ "name", "machineType", "canIpForward", "networkInterfaces", "disks", "description",
@ -140,14 +123,6 @@ public abstract class NewInstance {
private List<ServiceAccount> serviceAccounts;
private Scheduling scheduling;
public Builder(String name, URI machineType, URI network, List<AttachDisk> disks) {
checkNotNull(name, "NewInstance name cannot be null");
this.name = name;
this.machineType = machineType;
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network));
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;
@ -156,14 +131,6 @@ public abstract class NewInstance {
this.disks = disks;
}
public Builder(String name, URI machineType, URI network, URI sourceImage) {
checkNotNull(name, "NewInstance name cannot be null");
this.name = name;
this.machineType = machineType;
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network));
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;

View File

@ -48,13 +48,12 @@ public abstract class Subnetwork {
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);
@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

@ -43,7 +43,7 @@ import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
@ -66,7 +66,7 @@ public interface NetworkApi {
Network get(@PathParam("network") String networkName);
/**
* Creates a persistent network resource in the specified project with the specified range.
* Creates a legacy persistent network resource in the specified project with the specified range.
*
* @param networkName the network name
* @param IPv4Range the range of the network to be inserted.
@ -76,21 +76,33 @@ public interface NetworkApi {
@Named("Networks:insert")
@POST
@Produces(APPLICATION_JSON)
@MapBinder(BindToJsonPayload.class)
Operation createInIPv4Range(@PayloadParam("name") String networkName,
@PayloadParam("IPv4Range") String IPv4Range);
@Payload("%7B\"name\":\"{name}\",\"IPv4Range\":\"{IPv4Range}\"%7D")
Operation createLegacy(@PayloadParam("name") String networkName, @PayloadParam("IPv4Range") String IPv4Range);
/**
* Creates a persistent network resource in the specified project with the specified range and specified gateway.
* Creates a custom persistent network resource in the specified project with the specified range.
*
* @param options the options to create the network.
* @param networkName the network name
* @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("Networks:insert")
@POST
@Produces(APPLICATION_JSON)
Operation createInIPv4Range(@BinderParam(BindToJsonPayload.class) NetworkCreationOptions options);
@Payload("%7B\"autoCreateSubnetworks\":false,\"name\":\"{name}\"%7D")
Operation createCustom(@PayloadParam("name") String networkName);
/**
* Creates a persistent network resource in the specified project with the specified options.
*
* @param options the network options.
* @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("Networks:insert")
@POST
@Produces(APPLICATION_JSON)
Operation create(@BinderParam(BindToJsonPayload.class) NetworkCreationOptions options);
/** Deletes a network by name and returns the operation in progress, or null if not found. */
@Named("Networks:delete")
@ -124,7 +136,7 @@ public interface NetworkApi {
@Transform(NetworkPages.class)
Iterator<ListPage<Network>> list(ListOptions options);
final class NetworkPages extends BaseToIteratorOfListPage<Network, NetworkPages> {
static final class NetworkPages extends BaseToIteratorOfListPage<Network, NetworkPages> {
private final GoogleComputeEngineApi api;

View File

@ -18,7 +18,6 @@ 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;
@ -43,11 +42,7 @@ 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;
@ -107,6 +102,12 @@ public interface SubnetworkApi {
@GET
@Transform(SubnetworkPages.class)
Iterator<ListPage<Subnetwork>> list();
/** @see #listPage(String, ListOptions) */
@Named("Subnetworks:list")
@GET
@Transform(SubnetworkPages.class)
Iterator<ListPage<Subnetwork>> list(ListOptions options);
static final class SubnetworkPages extends BaseCallerArg0ToIteratorOfListPage<Subnetwork, SubnetworkPages> {

View File

@ -37,18 +37,20 @@ public abstract class NetworkCreationOptions {
* The range of internal addresses that are legal on this network. This range is a CIDR
* specification, for example: {@code 192.168.0.0/16}.
*/
public abstract String rangeIPv4();
@Nullable public abstract String rangeIPv4();
/**
* This must be within the range specified by IPv4Range, and is typically the first usable address in that range.
* If not specified, the default value is the first usable address in IPv4Range.
*/
@Nullable public abstract String gatewayIPv4();
@Nullable public abstract Boolean autoCreateSubnetworks();
@SerializedNames({ "name", "description", "IPv4Range", "gatewayIPv4" })
@SerializedNames({ "name", "description", "IPv4Range", "gatewayIPv4", "autoCreateSubnetworks" })
public static NetworkCreationOptions create(String name, String description, String rangeIPv4,
String gatewayIPv4) {
return new AutoValue_NetworkCreationOptions(name, description, rangeIPv4, gatewayIPv4);
String gatewayIPv4, Boolean autoCreateSubnetworks) {
return new AutoValue_NetworkCreationOptions(name, description, rangeIPv4, gatewayIPv4, autoCreateSubnetworks);
}
NetworkCreationOptions() {
@ -59,10 +61,15 @@ public abstract class NetworkCreationOptions {
private String description;
private String rangeIPv4;
private String gatewayIPv4;
public Builder(String name, String rangeIPv4){
private Boolean autoCreateSubnetworks;
public Builder(String name) {
this.name = name;
}
public Builder rangeIPv4(String rangeIPv4) {
this.rangeIPv4 = rangeIPv4;
return this;
}
public Builder description(String description) {
@ -74,11 +81,15 @@ public abstract class NetworkCreationOptions {
this.gatewayIPv4 = gatewayIPv4;
return this;
}
public Builder autoCreateSubnetworks(Boolean autoCreateSubnetworks) {
this.autoCreateSubnetworks = autoCreateSubnetworks;
return this;
}
public NetworkCreationOptions build() {
checkNotNull(name, "NetworkCreationOptions name cannot be null");
checkNotNull(rangeIPv4, "NetworkCreationOptions rangeIPv4 cannot be null");
return create(name, description, rangeIPv4, gatewayIPv4);
return create(name, description, rangeIPv4, gatewayIPv4, autoCreateSubnetworks);
}
}

View File

@ -16,8 +16,6 @@
*/
package org.jclouds.googlecomputeengine.options;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
@ -33,7 +31,8 @@ public abstract class SubnetworkCreationOptions {
public abstract String name();
@Nullable public abstract String description();
@Nullable
public abstract String description();
public abstract URI network();
@ -41,12 +40,16 @@ public abstract class SubnetworkCreationOptions {
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);
public abstract boolean privateIpGoogleAccess();
@SerializedNames({ "name", "description", "network", "ipCidrRange", "region", "privateIpGoogleAccess" })
public static SubnetworkCreationOptions create(String name, String description, URI network, String ipCidrRange,
URI region, boolean privateIpGoogleAccess) {
return new AutoValue_SubnetworkCreationOptions(name, description, network, ipCidrRange, region,
privateIpGoogleAccess);
}
SubnetworkCreationOptions() {
}
}

View File

@ -173,6 +173,7 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
server.enqueue(jsonResponse("/image_list.json"));
server.enqueue(jsonResponse("/image_list_debian.json")); // per IMAGE_PROJECTS = "debian-cloud"
server.enqueue(jsonResponse("/aggregated_machinetype_list.json"));
server.enqueue(new MockResponse().setResponseCode(404)); // Get Subnet
server.enqueue(jsonResponse("/network_get_default.json"));
server.enqueue(new MockResponse().setResponseCode(404)); // Get Firewall
server.enqueue(jsonResponse("/operation.json")); // Create Firewall
@ -199,6 +200,7 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
assertSent(server, "GET", "/projects/party/global/images");
assertSent(server, "GET", "/projects/debian-cloud/global/images");
assertSent(server, "GET", "/projects/party/aggregated/machineTypes");
assertSent(server, "GET", "/projects/party/regions/us-central1/subnetworks/default");
assertSent(server, "GET", "/projects/party/global/networks/default");
assertSent(server, "GET", "/projects/party/global/firewalls/jclouds-test-65f"); // Get Firewall
assertSent(server, "POST", "/projects/party/global/firewalls", // Create Firewall
@ -219,6 +221,7 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
server.enqueue(jsonResponse("/image_list.json"));
server.enqueue(jsonResponse("/image_list_debian.json")); // per IMAGE_PROJECTS = "debian-cloud"
server.enqueue(jsonResponse("/aggregated_machinetype_list.json"));
server.enqueue(new MockResponse().setResponseCode(404)); // Get Subnet
server.enqueue(jsonResponse("/network_get_default.json"));
server.enqueue(new MockResponse().setResponseCode(404)); // Get Firewall
server.enqueue(jsonResponse("/operation.json")); // Create Firewall
@ -248,6 +251,7 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
assertSent(server, "GET", "/projects/party/global/images");
assertSent(server, "GET", "/projects/debian-cloud/global/images");
assertSent(server, "GET", "/projects/party/aggregated/machineTypes");
assertSent(server, "GET", "/projects/party/regions/us-central1/subnetworks/default");
assertSent(server, "GET", "/projects/party/global/networks/default");
assertSent(server, "GET", "/projects/party/global/firewalls/jclouds-test-65f"); // Get Firewall
assertSent(server, "POST", "/projects/party/global/firewalls", // Create Firewall
@ -263,6 +267,58 @@ public class GoogleComputeEngineServiceMockTest extends BaseGoogleComputeEngineA
assertSent(server, "GET", "/projects/party/zones/us-central1-a/instances/test-1");
}
public void createNodeWithCustomSubnetwork() throws Exception {
server.enqueue(singleRegionSingleZoneResponse());
server.enqueue(jsonResponse("/image_list.json"));
server.enqueue(jsonResponse("/image_list_debian.json")); // per IMAGE_PROJECTS = "debian-cloud"
server.enqueue(jsonResponse("/aggregated_machinetype_list.json"));
server.enqueue(jsonResponse("/subnetwork_get.json"));
server.enqueue(jsonResponse("/network_get.json"));
server.enqueue(new MockResponse().setResponseCode(404)); // Get Firewall
server.enqueue(jsonResponse("/operation.json")); // Create Firewall
server.enqueue(jsonResponse("/zone_operation.json"));
server.enqueue(aggregatedListWithInstanceNetworkAndStatus("test-0", "test-network", RUNNING));
server.enqueue(jsonResponse("/disk_get_with_source_image.json"));
server.enqueue(jsonResponse("/image_get_for_source_image.json"));
server.enqueue(jsonResponse("/disktype_ssd.json"));
server.enqueue(jsonResponse("/operation.json")); // Create Instance
server.enqueue(instanceWithNetworkAndStatusAndSsd("test-1", "test-network", RUNNING));
ComputeService computeService = computeService();
GoogleComputeEngineTemplateOptions options = computeService.templateOptions()
.as(GoogleComputeEngineTemplateOptions.class).autoCreateKeyPair(false)
.tags(ImmutableSet.of("aTag")).blockUntilRunning(false)
.bootDiskType("pd-ssd").networks("jclouds-test");
Template template = computeService.templateBuilder().options(options).build();
NodeMetadata node = getOnlyElement(computeService.createNodesInGroup("test", 1, template));
// prove our caching works.
assertEquals(node.getImageId(), template.getImage().getId());
assertEquals(node.getLocation().getId(), template.getLocation().getId());
assertSent(server, "GET", "/projects/party/regions");
assertSent(server, "GET", "/projects/party/global/images");
assertSent(server, "GET", "/projects/debian-cloud/global/images");
assertSent(server, "GET", "/projects/party/aggregated/machineTypes");
assertSent(server, "GET", "/projects/party/regions/us-central1/subnetworks/jclouds-test");
assertSent(server, "GET", "/projects/party/global/networks/mynetwork");
assertSent(server, "GET", "/projects/party/global/firewalls/jclouds-test-65f"); // Get Firewall
assertSent(server, "POST", "/projects/party/global/firewalls", // Create Firewall
stringFromResource("/firewall_insert_3.json"));
assertSent(server, "GET", "/projects/party/zones/us-central1-a/operations/operation-1354084865060");
assertSent(server, "GET", "/projects/party/aggregated/instances");
assertSent(server, "GET", "/projects/party/zones/us-central1-a/disks/test");
assertSent(server, "GET", "/projects/debian-cloud/global/images/debian-7-wheezy-v20140718");
assertSent(server, "GET", "/projects/party/zones/us-central1-a/diskTypes/pd-ssd");
assertSent(server, "POST", "/projects/party/zones/us-central1-a/instances",
String.format(stringFromResource("/instance_insert_subnet.json"), template.getHardware().getId(), template.getImage().getId()));
assertSent(server, "GET", "/projects/party/zones/us-central1-a/instances/test-1");
}
private MockResponse instanceWithNetworkAndStatus(String instanceName, String networkName, Instance.Status status) {
return new MockResponse().setBody(

View File

@ -24,12 +24,14 @@ import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiMockTest;
import org.jclouds.googlecomputeengine.parse.ParseDiskTest;
import org.jclouds.googlecomputeengine.parse.ParseImageTest;
import org.jclouds.googlecomputeengine.parse.ParseInstanceTest;
import org.jclouds.googlecomputeengine.parse.ParseNetworkTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.googlecomputeengine.parse.ParseSubnetworkTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ResourcesMockTest", singleThreaded = true)
@ -155,6 +157,22 @@ public class ResourcesMockTest extends BaseGoogleComputeEngineApiMockTest {
assertSent(server, "POST", "/foo/bar/start");
}
public void testSubnetwork() throws Exception {
server.enqueue(jsonResponse("/subnetwork_get.json"));
Subnetwork subnet = resourceApi().subnetwork(server.getUrl("/foo/bar").toURI());
assertEquals(subnet, new ParseSubnetworkTest().expected(url("/projects")));
assertSent(server, "GET", "/foo/bar");
}
public void testSubnetworkReturns404() throws Exception {
server.enqueue(response404());
Subnetwork subnet = resourceApi().subnetwork(server.getUrl("/foo/bar").toURI());
assertNull(subnet);
assertSent(server, "GET", "/foo/bar");
}
private Resources resourceApi() {
return builder().build().utils().injector().getInstance(Resources.class);
}

View File

@ -45,8 +45,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@Test(groups = "live")
public void testInsertFirewall() {
// need to insert the network first
assertOperationDoneSuccessfully(
api.networks().createInIPv4Range(FIREWALL_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.networks().createLegacy(FIREWALL_NETWORK_NAME, IPV4_RANGE));
FirewallOptions firewall = new FirewallOptions()
.addAllowedRule(Firewall.Rule.create("tcp", ImmutableList.of("22")))

View File

@ -30,18 +30,18 @@ import java.util.Properties;
import org.jclouds.googlecloud.domain.ListPage;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.AttachDisk;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling;
import org.jclouds.googlecomputeengine.domain.Instance.Scheduling.OnHostMaintenance;
import org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
import org.jclouds.googlecomputeengine.domain.Metadata;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.domain.AttachDisk;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Tags;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
@ -96,6 +96,7 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
INSTANCE_NAME, // name
getDefaultMachineTypeUrl(), // machineType
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
null, // subnetwork
Arrays.asList(AttachDisk.newBootDisk(imageUri),
AttachDisk.existingDisk(getDiskUrl(DISK_NAME))), // disks
"a description", // description
@ -106,6 +107,7 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
instance2 = new NewInstance.Builder(INSTANCE_NAME2, // name
getDefaultMachineTypeUrl(), // machineType
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
null, // subnetwork
imageUri) // sourceImage
.canIpForward(true)
.description("description")
@ -141,8 +143,7 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@Test(groups = "live")
public void testInsertInstance() {
// need to insert the network first
assertOperationDoneSuccessfully(api.networks().createInIPv4Range
(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.networks().createLegacy(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(diskApi().create(DISK_NAME,
new DiskCreationOptions.Builder().sizeGb(DEFAULT_DISK_SIZE_GB).build()));

View File

@ -86,6 +86,7 @@ public class InstanceApiMockTest extends BaseGoogleComputeEngineApiMockTest {
"test-1", // name
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
URI.create(url("/projects/party/global/networks/default")), // network
null, // subnetwork
URI.create(url("/projects/party/global/images/centos-6-2-v20120326")) // sourceImage
);
@ -101,6 +102,7 @@ public class InstanceApiMockTest extends BaseGoogleComputeEngineApiMockTest {
"test-1", // name
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
URI.create(url("/projects/party/global/networks/default")), // network
null, // subnetwork
Arrays.asList(AttachDisk.existingBootDisk(URI.create(url("/projects/party/zones/us-central1-a/disks/test")))),
"desc", // description
null // tags
@ -270,6 +272,7 @@ public class InstanceApiMockTest extends BaseGoogleComputeEngineApiMockTest {
NewInstance newInstance = new NewInstance.Builder("test-1", // name
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
URI.create(url("/projects/party/global/networks/default")), // network
null, // subnetwork
URI.create(url("/projects/party/global/images/centos-6-2-v20120326"))).build(); // sourceImage)
assertEquals(instanceApi().create(newInstance), new ParseZoneOperationTest().expected(url("/projects")));
@ -284,6 +287,7 @@ public class InstanceApiMockTest extends BaseGoogleComputeEngineApiMockTest {
"test-1", // name
URI.create(url("/projects/party/zones/us-central1-a/machineTypes/n1-standard-1")), // machineType
URI.create(url("/projects/party/global/networks/default")), // network
null, // subnetwork
Arrays.asList(AttachDisk.existingBootDisk(URI.create(url("/projects/party/zones/us-central1-a/disks/test")))))
.canIpForward(true)
.description("desc")

View File

@ -16,24 +16,8 @@
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.DiskCreationOptions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.options.ListOptions.Builder.filter;
import static org.testng.Assert.assertFalse;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
@ -44,8 +28,25 @@ import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import static org.jclouds.googlecomputeengine.options.ListOptions.Builder.filter;
import static org.testng.Assert.assertFalse;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.DiskCreationOptions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@Test(groups = "live", testName = "InstanceApiWindowsLiveTest")
public class InstanceApiWindowsLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@ -80,6 +81,7 @@ public class InstanceApiWindowsLiveTest extends BaseGoogleComputeEngineApiLiveTe
INSTANCE_NAME,
getDefaultMachineTypeUrl(),
getNetworkUrl(INSTANCE_NETWORK_NAME),
null,
imageUri
);
@ -102,8 +104,7 @@ public class InstanceApiWindowsLiveTest extends BaseGoogleComputeEngineApiLiveTe
@Test(groups = "live")
public void testInsertInstanceWindows() {
// need to insert the network first
assertOperationDoneSuccessfully(api.networks().createInIPv4Range
(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.networks().createLegacy(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(diskApi().create(DISK_NAME,
new DiskCreationOptions.Builder().sizeGb(DEFAULT_DISK_SIZE_GB).build()));

View File

@ -40,7 +40,7 @@ public class NetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@Test(groups = "live")
public void testInsertNetwork() {
assertOperationDoneSuccessfully(api().createInIPv4Range(NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api().createLegacy(NETWORK_NAME, IPV4_RANGE));
}
@Test(groups = "live", dependsOnMethods = "testInsertNetwork")

View File

@ -44,13 +44,21 @@ public class NetworkApiMockTest extends BaseGoogleComputeEngineApiMockTest {
assertSent(server, "GET", "/projects/party/global/networks/jclouds-test");
}
public void insert() throws Exception {
public void insertLegacy() throws Exception {
server.enqueue(jsonResponse("/operation.json"));
assertEquals(networkApi().createInIPv4Range("test-network", "10.0.0.0/8"), new ParseOperationTest().expected(url("/projects")));
assertEquals(networkApi().createLegacy("test-network", "10.0.0.0/8"), new ParseOperationTest().expected(url("/projects")));
assertSent(server, "POST", "/projects/party/global/networks",
stringFromResource("/network_insert.json"));
}
public void insertCustom() throws Exception {
server.enqueue(jsonResponse("/operation.json"));
assertEquals(networkApi().createCustom("test-network"), new ParseOperationTest().expected(url("/projects")));
assertSent(server, "POST", "/projects/party/global/networks",
stringFromResource("/network_insert_custom.json"));
}
public void delete() throws Exception {
server.enqueue(jsonResponse("/operation.json"));

View File

@ -43,8 +43,7 @@ public class RouteApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@Test(groups = "live")
public void testInsertRoute() {
assertOperationDoneSuccessfully(api.networks().createInIPv4Range
(ROUTE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.networks().createLegacy(ROUTE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api().createInNetwork(ROUTE_NAME,
getNetworkUrl(ROUTE_NETWORK_NAME),
new RouteOptions().addTag("footag")

View File

@ -0,0 +1,80 @@
/*
* 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.jclouds.googlecomputeengine.options.ListOptions.Builder.filter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.Iterator;
import java.util.List;
import org.jclouds.googlecloud.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.SubnetworkCreationOptions;
import org.testng.annotations.Test;
@Test(groups = "live", testName = "SubnetworkApiLiveTest")
public class SubnetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String SUBNETWORK_NAME = "subnetwork-api-live-test-network";
private static final String SUBNETWORK_RANGE = "10.0.0.0/8";
private SubnetworkApi api() {
return api.subnetworksInRegion(DEFAULT_REGION_NAME);
}
@Test
public void testInsertSubnetwork() {
assertOperationDoneSuccessfully(api.networks().createCustom(SUBNETWORK_NAME));
Network network = api.networks().get(SUBNETWORK_NAME);
assertNotNull(network);
SubnetworkCreationOptions opts = SubnetworkCreationOptions.create(SUBNETWORK_NAME, SUBNETWORK_NAME,
network.selfLink(), SUBNETWORK_RANGE, getDefaultRegionUrl(), false);
assertOperationDoneSuccessfully(api().createInNetwork(opts));
}
@Test(dependsOnMethods = "testInsertSubnetwork")
public void testGetSubnetwork() {
Subnetwork subnet = api().get(SUBNETWORK_NAME);
assertNotNull(subnet);
assertSubnetworkEquals(subnet);
}
@Test(dependsOnMethods = "testInsertSubnetwork")
public void testListSubnetworks() {
Iterator<ListPage<Subnetwork>> subnets = api().list(filter("name eq " + SUBNETWORK_NAME));
List<Subnetwork> subnetsAsList = subnets.next();
assertEquals(subnetsAsList.size(), 1);
assertSubnetworkEquals(subnetsAsList.get(0));
}
@Test(dependsOnMethods = { "testListSubnetworks", "testGetSubnetwork" }, alwaysRun = true)
public void testDeleteSubnetwork() {
assertOperationDoneSuccessfully(api().delete(SUBNETWORK_NAME));
assertOperationDoneSuccessfully(api.networks().delete(SUBNETWORK_NAME));
}
private void assertSubnetworkEquals(Subnetwork result) {
assertEquals(result.name(), SUBNETWORK_NAME);
assertEquals(result.ipCidrRange(), SUBNETWORK_RANGE);
}
}

View File

@ -55,7 +55,8 @@ public class SubnetworkApiMockTest extends BaseGoogleComputeEngineApiMockTest {
"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")));
URI.create(url("/projects/party/regions/someregion")),
false)), new ParseOperationTest().expected(url("/projects")));
assertSent(server, "POST", "/projects/party/regions/someregion/subnetworks",
stringFromResource("/subnetwork_insert.json"));
}

View File

@ -69,11 +69,12 @@ public class TargetInstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTes
INSTANCE_NAME, // name
getDefaultMachineTypeUrl(), // machineType
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
null, // subnetwork
imageUri);
// need to insert the network first
assertOperationDoneSuccessfully(api.networks().createInIPv4Range
(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.networks().createLegacy(INSTANCE_NETWORK_NAME, IPV4_RANGE));
assertOperationDoneSuccessfully(api.instancesInZone(DEFAULT_ZONE_NAME).create(newInstance));
instance = api.instancesInZone(DEFAULT_ZONE_NAME).get(INSTANCE_NAME);
assertNotNull(instance);

View File

@ -26,13 +26,13 @@ import java.util.ArrayList;
import java.util.List;
import org.jclouds.googlecloud.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.ForwardingRule.IPProtocol;
import org.jclouds.googlecomputeengine.domain.HealthStatus;
import org.jclouds.googlecomputeengine.domain.HttpHealthCheck;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.domain.TargetPool;
import org.jclouds.googlecomputeengine.domain.ForwardingRule.IPProtocol;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ForwardingRuleCreationOptions;
import org.jclouds.googlecomputeengine.options.HttpHealthCheckCreationOptions;
@ -84,9 +84,8 @@ public class TargetPoolApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
})
.first().get().selfLink();
// Insert a network.
assertOperationDoneSuccessfully(api.networks().createInIPv4Range(INSTANCE_NETWORK_NAME,
IPV4_RANGE));
// need to insert the network first
assertOperationDoneSuccessfully(api.networks().createLegacy(INSTANCE_NETWORK_NAME, IPV4_RANGE));
// Create an instance.
assertOperationDoneSuccessfully(
@ -94,6 +93,7 @@ public class TargetPoolApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
INSTANCE_NAME, // name
getDefaultMachineTypeUrl(), // machineType
getNetworkUrl(INSTANCE_NETWORK_NAME), // network
null, // subnetwork
imageUri // disks
)));

View File

@ -48,6 +48,7 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
protected static final String ZONE_API_URL_SUFFIX = "/zones/";
protected static final String DEFAULT_ZONE_NAME = "us-central1-f";
protected static final String REGION_API_URL_SUFFIX = "/regions/";
protected static final String DEFAULT_REGION_NAME = "us-central1";
protected static final String NETWORK_API_URL_SUFFIX = "/global/networks/";
protected static final String MACHINE_TYPE_API_URL_SUFFIX = "/machineTypes/";
@ -116,6 +117,14 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
protected URI getZoneUrl(String zone) {
return URI.create(projectUrl + ZONE_API_URL_SUFFIX + zone);
}
protected URI getDefaultRegionUrl() {
return getRegionUrl(DEFAULT_REGION_NAME);
}
protected URI getRegionUrl(String region) {
return URI.create(projectUrl + REGION_API_URL_SUFFIX + region);
}
protected URI getNetworkUrl(String network) {
return URI.create(projectUrl + NETWORK_API_URL_SUFFIX + network);
@ -162,5 +171,9 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
protected URI getUrlMapUrl(String urlMap) {
return URI.create(projectUrl + URL_MAP_API_URL_SUFFIX + urlMap);
}
protected URI getSubnetworkUrl(String region, String subnetName) {
return URI.create(projectUrl + REGION_API_URL_SUFFIX + region + "/subnetworks/" + subnetName);
}
}

View File

@ -19,6 +19,7 @@ package org.jclouds.googlecomputeengine.parse;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import java.net.URI;
import java.util.Collections;
import javax.ws.rs.Consumes;
@ -48,7 +49,9 @@ public class ParseNetworkTest extends BaseGoogleComputeEngineParseTest<Network>
"jclouds-test", // name
"A custom network for the project", // description
"10.0.0.0/8", // rangeIPv4
"10.0.0.1" // gatewayIPv4
"10.0.0.1", // gatewayIPv4
false,
Collections.<URI> emptyList() // subnetworks
);
}
}

View File

@ -33,7 +33,7 @@ public class ParseSubnetworkListTest extends BaseGoogleComputeEngineParseTest<Li
@Override
public String resource() {
return "/network_list.json";
return "/subnetwork_list.json";
}
@Override @Consumes(APPLICATION_JSON)

View File

@ -31,7 +31,7 @@ public class ParseSubnetworkTest extends BaseGoogleComputeEngineParseTest<Subnet
@Override
public String resource() {
return "/network_get.json";
return "/subnetwork_get.json";
}
@Override @Consumes(APPLICATION_JSON)
@ -45,7 +45,7 @@ public class ParseSubnetworkTest extends BaseGoogleComputeEngineParseTest<Subnet
"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
"jclouds-test", // name
"A custom subnetwork for the project", // description
"10.128.0.1",
URI.create(baseUrl + "/party/global/networks/mynetwork"), // network

View File

@ -0,0 +1,28 @@
{
"name": "jclouds-test-65f",
"network": "https://www.googleapis.com/compute/v1/projects/party/networks/jclouds-test",
"sourceRanges": [
"10.128.0.0/20",
"0.0.0.0/0"
],
"sourceTags": [
"aTag"
],
"targetTags": [
"jclouds-test-65f"
],
"allowed": [
{
"IPProtocol": "tcp",
"ports": [
"22"
]
},
{
"IPProtocol": "udp",
"ports": [
"22"
]
}
]
}

View File

@ -0,0 +1,46 @@
{
"machineType": "%s",
"name": "test-1",
"networkInterfaces": [
{
"network": "https://www.googleapis.com/compute/v1/projects/party/global/networks/mynetwork",
"subnetwork": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion/subnetworks/jclouds-test",
"accessConfigs": [
{
"type": "ONE_TO_ONE_NAT"
}
]
}
],
"disks": [
{
"type": "PERSISTENT",
"initializeParams": {
"sourceImage": "%s",
"diskType": "https://content.googleapis.com/compute/v1/projects/party/zones/us-central1-a/diskTypes/pd-ssd"
},
"boot": true,
"autoDelete": true
}
],
"description": "test",
"tags": {
"items": [
"aTag",
"jclouds-test-65f"
]
},
"metadata": {
"items": [
{
"key": "jclouds-group",
"value": "test"
}
]
},
"scheduling": {
"onHostMaintenance": "MIGRATE",
"automaticRestart": true,
"preemptible": false
}
}

View File

@ -6,5 +6,6 @@
"name": "jclouds-test",
"description": "A custom network for the project",
"IPv4Range": "10.0.0.0/8",
"gatewayIPv4": "10.0.0.1"
"gatewayIPv4": "10.0.0.1",
"subnetworks": []
}

View File

@ -0,0 +1 @@
{"autoCreateSubnetworks":false,"name":"test-network"}

View File

@ -3,7 +3,7 @@
"id": "5850679262666457680",
"creationTimestamp": "2016-06-07T14:29:35.476-07:00",
"gatewayAddress": "10.128.0.1",
"name": "jclouds-subnetwork-test",
"name": "jclouds-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",

View File

@ -3,5 +3,6 @@
"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"
"region": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion",
"privateIpGoogleAccess": false
}

View File

@ -8,7 +8,7 @@
"id": "5850679262666457680",
"creationTimestamp": "2016-06-07T14:29:35.476-07:00",
"gatewayAddress": "10.128.0.1",
"name": "jclouds-subnetwork-test",
"name": "jclouds-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",