You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/11/09 19:17:06 UTC
[7/8] jclouds-labs-google git commit: * Rewrites InstanceTemplate as
NewInstance,
strictly from docs. * Rewrites Metadata to have the same shape as in json,
avoid really complicated json parser. * Rewrites
GoogleComputeEngineServiceAdapter.createNodeW
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
new file mode 100644
index 0000000..a1eaf36
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
@@ -0,0 +1,83 @@
+/*
+ * 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.functions;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableSet;
+
+public final class MachineTypeToHardware implements Function<MachineType, Hardware> {
+
+ private final Supplier<Map<URI, Location>> locationsByUri;
+
+ @Inject MachineTypeToHardware(@Memoized Supplier<Map<URI, Location>> locationsByUri) {
+ this.locationsByUri = locationsByUri;
+ }
+
+ @Override
+ public Hardware apply(MachineType input) {
+ URI zoneLink = URI.create(
+ input.selfLink().toString().replace("/machineTypes/" + input.name(), ""));
+
+ Location zone = locationsByUri.get().get(zoneLink);
+ if (zone == null) {
+ throw new IllegalStateException(
+ String.format("zone %s not present in %s", zoneLink, locationsByUri.get().keySet()));
+ }
+ return new HardwareBuilder()
+ .id(input.selfLink().toString())
+ .providerId(input.id())
+ .location(zone)
+ .name(input.name())
+ .hypervisor("kvm")
+ .processor(new Processor(input.guestCpus(), 1.0))
+ .providerId(input.id())
+ .ram(input.memoryMb())
+ .uri(input.selfLink())
+ .volumes(collectVolumes(input))
+ .supportsImage(Predicates.<Image>alwaysTrue())
+ .build();
+ }
+
+ private Iterable<Volume> collectVolumes(MachineType input) {
+ ImmutableSet.Builder<Volume> volumes = ImmutableSet.builder();
+ for (MachineType.ScratchDisk disk : input.scratchDisks()) {
+ volumes.add(new VolumeBuilder()
+ .type(Volume.Type.LOCAL)
+ .size(Float.valueOf(disk.diskGb()))
+ .bootDevice(true)
+ .durable(false).build());
+ }
+ return volumes.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ResourceFunctions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ResourceFunctions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ResourceFunctions.java
deleted file mode 100644
index 6b16725..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ResourceFunctions.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.functions;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
-
-import java.net.URI;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.oauth.v2.config.OAuthScopes;
-import org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SkipEncoding;
-
-@SkipEncoding({'/', '='})
-@RequestFilters(OAuthAuthenticationFilter.class)
-@Consumes(APPLICATION_JSON)
-public interface ResourceFunctions {
-
- /** Returns an instance by self-link or null if not found. */
- @Named("Instances:get")
- @GET
- @OAuthScopes(COMPUTE_READONLY_SCOPE)
- @Fallback(NullOnNotFoundOr404.class) @Nullable Instance instance(@EndpointParam URI selfLink);
-
- /** Returns an operation by self-link or null if not found. */
- @Named("Operations:get")
- @GET
- @OAuthScopes(COMPUTE_READONLY_SCOPE)
- @Fallback(NullOnNotFoundOr404.class) @Nullable Operation operation(@EndpointParam URI selfLink);
-}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/Resources.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/Resources.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/Resources.java
new file mode 100644
index 0000000..34d7d54
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/Resources.java
@@ -0,0 +1,85 @@
+/*
+ * 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.functions;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+
+import java.net.URI;
+
+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 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.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SkipEncoding;
+
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticationFilter.class)
+@Consumes(APPLICATION_JSON)
+public interface Resources {
+
+ /** Returns an image by self-link or null if not found. */
+ @Named("Images:get")
+ @GET
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class) @Nullable Image image(@EndpointParam URI selfLink);
+
+ /** Returns an instance by self-link or null if not found. */
+ @Named("Instances:get")
+ @GET
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class) @Nullable Instance instance(@EndpointParam URI selfLink);
+
+ /** Returns an network by self-link or null if not found. */
+ @Named("Networks:get")
+ @GET
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class) @Nullable Network network(@EndpointParam URI selfLink);
+
+ /** Returns an operation by self-link or null if not found. */
+ @Named("Operations:get")
+ @GET
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class) @Nullable Operation operation(@EndpointParam URI selfLink);
+
+ /** Deletes any resource by self-link and returns the operation in progress, or null if not found. */
+ @Named("Resources:delete")
+ @DELETE
+ @OAuthScopes(COMPUTE_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class) @Nullable Operation delete(@EndpointParam URI selfLink);
+
+ /** Hard-resets the instance by self-link and returns the operation in progres */
+ @Named("Instances:reset")
+ @POST
+ @Path("/reset")
+ @OAuthScopes(COMPUTE_SCOPE) Operation resetInstance(@EndpointParam URI selfLink);
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
index c6e5f69..3aabae3 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
@@ -16,34 +16,22 @@
*/
package org.jclouds.googlecomputeengine.compute.options;
-import static com.google.common.base.Optional.fromNullable;
-import static org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
-
import java.net.URI;
import java.util.List;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.domain.templates.InstanceTemplate.PersistentDisk;
+import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-/**
- * Instance options specific to Google Compute Engine.
- */
+/** Instance options specific to Google Compute Engine. */
public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
- private Optional<URI> network = Optional.absent();
- private List<Instance.ServiceAccount> serviceAccounts = Lists.newArrayList();
- private boolean enableNat = true;
- private List<PersistentDisk> disks = Lists.newArrayList();
- private Optional<Long> bootDiskSize = Optional.absent();
- private boolean keepBootDisk = false;
+ private URI network = null;
+ private final List<URI> additionalDisks = Lists.newArrayList();
@Override
public GoogleComputeEngineTemplateOptions clone() {
@@ -57,89 +45,25 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
super.copyTo(to);
if (to instanceof GoogleComputeEngineTemplateOptions) {
GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to);
- eTo.network(getNetwork().orNull());
- eTo.serviceAccounts(getServiceAccounts());
- eTo.enableNat(isEnableNat());
- eTo.disks(getDisks());
- eTo.keepBootDisk(shouldKeepBootDisk());
+ eTo.network(network());
}
}
- /**
- * @deprecated See TemplateOptions#networks
- * @see #getNetworkName()
- */
- @Deprecated
- public GoogleComputeEngineTemplateOptions network(String networkName) {
- return this.networks(networkName);
- }
-
- /**
- * @see #getNetwork()
- */
+ /** @see #network() */
public GoogleComputeEngineTemplateOptions network(URI network) {
- this.network = fromNullable(network);
- return this;
- }
-
- /**
- * @see #getServiceAccounts()
- * @see ServiceAccount
- */
- public GoogleComputeEngineTemplateOptions addServiceAccount(ServiceAccount serviceAccout) {
- this.serviceAccounts.add(serviceAccout);
- return this;
- }
-
- /**
- * @see #getServiceAccounts()
- * @see ServiceAccount
- */
- public GoogleComputeEngineTemplateOptions serviceAccounts(List<ServiceAccount> serviceAccounts) {
- this.serviceAccounts = Lists.newArrayList(serviceAccounts);
+ this.network = network;
return this;
}
- /**
- * @see #getDisks()
- * @see org.jclouds.googlecomputeengine.domain.templates.InstanceTemplate.PersistentDisk
- */
- public GoogleComputeEngineTemplateOptions addDisk(PersistentDisk disk) {
- this.disks.add(disk);
- return this;
- }
-
- /**
- * @see #getDisks()
- * @see org.jclouds.googlecomputeengine.domain.templates.InstanceTemplate.PersistentDisk
- */
- public GoogleComputeEngineTemplateOptions disks(List<PersistentDisk> disks) {
- this.disks = Lists.newArrayList(disks);
- return this;
- }
-
- /**
- * @see #isEnableNat()
- */
- public GoogleComputeEngineTemplateOptions enableNat(boolean enableNat) {
- this.enableNat = enableNat;
- return this;
- }
-
- /**
- * @see #getBootDiskSize()
- */
- public GoogleComputeEngineTemplateOptions bootDiskSize(Long bootDiskSize) {
- this.bootDiskSize = fromNullable(bootDiskSize);
- return this;
+ /** The network instances will attach to. When absent, a new network will be created for the project. */
+ @Nullable public URI network() {
+ return network;
}
- /**
- * @see #shouldKeepBootDisk()
- */
- public GoogleComputeEngineTemplateOptions keepBootDisk(boolean keepBootDisk) {
- this.keepBootDisk = keepBootDisk;
- return this;
+ /** Additional disks to attach to this instance. */
+ // TODO: test me or remove me!
+ public List<URI> additionalDisks() {
+ return additionalDisks;
}
/**
@@ -325,57 +249,4 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
public GoogleComputeEngineTemplateOptions blockOnComplete(boolean blockOnComplete) {
return GoogleComputeEngineTemplateOptions.class.cast(super.blockOnComplete(blockOnComplete));
}
-
- /**
- * @return the ServiceAccounts to enable in the instances.
- */
- public List<Instance.ServiceAccount> getServiceAccounts() {
- return serviceAccounts;
- }
-
- /**
- * @return the PersistentDisks for this instance.
- */
- public List<PersistentDisk> getDisks() {
- return disks;
- }
-
- /**
- * @return the URI of an existing network the instances will be attached to. If no network URI or network name are
- * provided a new network will be created for the project.
- */
- public Optional<URI> getNetwork() {
- return network;
- }
-
- /**
- * @return the name of an existing network the instances will be attached to, the network is assumed to belong to
- * user's project. If no network URI network name are provided a new network will be created for the project.
- * <b>Note that this is now pulling from the first element in the networks field from TemplateOptions.</b>
- */
- public Optional<String> getNetworkName() {
- return fromNullable(Iterables.getFirst(getNetworks(), null));
- }
-
- /**
- * @return whether an AccessConfig with Type ONE_TO_ONE_NAT should be enabled in the instances. When true
- * instances will have a NAT address that will be publicly accessible.
- */
- public boolean isEnableNat() {
- return enableNat;
- }
-
- /**
- * @return the boot disk size, if specified. Defaults to 10gb.
- */
- public Optional<Long> getBootDiskSize() {
- return bootDiskSize;
- }
-
- /**
- * @return whether we should keep the boot disk around when deleting the instance. Defaults to false.
- */
- public boolean shouldKeepBootDisk() {
- return keepBootDisk;
- }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicInstanceVisible.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicInstanceVisible.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicInstanceVisible.java
index 09d4486..ab7a512 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicInstanceVisible.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicInstanceVisible.java
@@ -20,16 +20,16 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
-import org.jclouds.googlecomputeengine.compute.functions.ResourceFunctions;
+import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.domain.Instance;
import com.google.common.base.Predicate;
public final class AtomicInstanceVisible implements Predicate<AtomicReference<Instance>> {
- private final ResourceFunctions resources;
+ private final Resources resources;
- @Inject AtomicInstanceVisible(ResourceFunctions resources) {
+ @Inject AtomicInstanceVisible(Resources resources) {
this.resources = resources;
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicOperationDone.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicOperationDone.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicOperationDone.java
index afe0dd0..1f917ae 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicOperationDone.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AtomicOperationDone.java
@@ -23,16 +23,16 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
-import org.jclouds.googlecomputeengine.compute.functions.ResourceFunctions;
+import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.domain.Operation;
import com.google.common.base.Predicate;
public final class AtomicOperationDone implements Predicate<AtomicReference<Operation>> {
- private final ResourceFunctions resources;
+ private final Resources resources;
- @Inject AtomicOperationDone(ResourceFunctions resources) {
+ @Inject AtomicOperationDone(Resources resources) {
this.resources = resources;
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
index ee2c877..3900c46 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -19,6 +19,7 @@ package org.jclouds.googlecomputeengine.compute.strategy;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.of;
+import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -118,9 +119,7 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
* Try and find a network either previously created by jclouds or user defined.
*/
private Network getOrCreateNetwork(GoogleComputeEngineTemplateOptions templateOptions, String sharedResourceName) {
-
- String networkName = templateOptions.getNetworkName().or(sharedResourceName);
-
+ String networkName = templateOptions.network() != null ? toName(templateOptions.network()) : sharedResourceName;
return networkMap.apply(NetworkAndAddressRange.create(networkName, DEFAULT_INTERNAL_NETWORK_RANGE, null));
}
@@ -166,4 +165,9 @@ public final class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
operation);
}
}
+
+ private static String toName(URI link) {
+ String path = link.getPath();
+ return path.substring(path.lastIndexOf('/') + 1);
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
index 20e26d7..4b14d7a 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
@@ -49,18 +49,12 @@ public final class GoogleComputeEngineHttpApiModule extends HttpApiModule<Google
public GoogleComputeEngineHttpApiModule() {
}
- @Override
- protected void bindErrorHandlers() {
+ @Override protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoogleComputeEngineErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoogleComputeEngineErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleComputeEngineErrorHandler.class);
}
- @Override
- protected void installLocations() {
- install(new GoogleComputeEngineLocationModule());
- }
-
/**
* Since this is caching a direct api call, we memoize, but short-circuit on any auth exception. This prevents
* excessive errors when things occur in parallel, or as peers on a function graph.
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineLocationModule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineLocationModule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineLocationModule.java
deleted file mode 100644
index 03d0e9d..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineLocationModule.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.config;
-
-import static com.google.common.base.Suppliers.compose;
-import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static org.jclouds.googlecomputeengine.internal.ListPages.concat;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.collect.Memoized;
-import org.jclouds.domain.Location;
-import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
-import org.jclouds.googlecomputeengine.domain.Region;
-import org.jclouds.location.config.LocationModule;
-import org.jclouds.location.predicates.LocationPredicates;
-import org.jclouds.location.reference.LocationConstants;
-import org.jclouds.location.suppliers.ImplicitLocationSupplier;
-import org.jclouds.location.suppliers.LocationsSupplier;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
-import org.jclouds.location.suppliers.RegionIdsSupplier;
-import org.jclouds.location.suppliers.ZoneIdToURISupplier;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
-import org.jclouds.location.suppliers.all.ZoneToRegionToProviderOrJustProvider;
-import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
-import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
-import org.jclouds.location.suppliers.implicit.FirstZone;
-import org.jclouds.rest.AuthorizationException;
-import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import com.google.inject.Provides;
-
-/**
- * This configures dynamic locations from {@link org.jclouds.googlecomputeengine.features.RegionApi#list}. As the only
- * assignable location for nodes are zones, this module does not directly expose regions. Rather, they can be found by
- * looking at {@link Location#getParent()} on a zone.
-
- * <p/> This does not yet support constraining region or zone lists via settings {@linkplain
- * LocationConstants#PROPERTY_REGIONS} or {@linkplain LocationConstants#PROPERTY_ZONES}.
- */
-public final class GoogleComputeEngineLocationModule extends LocationModule {
-
- @Override protected void configure() {
- super.configure();
- // Unlike EC2, you cannot default GCE instances to a region. Hence, we constrain to zones.
- bind(LocationsSupplier.class).to(OnlyZonesLocationSupplier.class);
- bind(ImplicitLocationSupplier.class).to(FirstZone.class);
-
- // Region and zones are derived from the same network request to RegionApi.list
- // Using these suppliers will make that consistent and also cache timeout consistently
- bind(RegionIdToZoneIdsSupplier.class).to(RegionIdToZoneIdsFromRegionList.class);
- bind(RegionIdToURISupplier.class).to(RegionIdToURISupplierFromRegionList.class);
- bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromRegionList.class);
- bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class);
- bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
- }
-
- /** Retain the metadata tree, including regions, just don't present anything except zones as assignable. */
- static final class OnlyZonesLocationSupplier implements LocationsSupplier {
- // This correctly links parents for zone -> region -> provider.
- private final ZoneToRegionToProviderOrJustProvider delegate;
-
- @Inject OnlyZonesLocationSupplier(ZoneToRegionToProviderOrJustProvider delegate) {
- this.delegate = delegate;
- }
-
- @Override public Set<? extends Location> get() {
- return Sets.filter(delegate.get(), LocationPredicates.isZone());
- }
- }
-
- /**
- * Since this is caching a direct api call, we memoize, but short-circuit on any auth exception. This prevents
- * excessive errors when things occur in parallel, or as peers on a function graph.
- */
- @Provides @Singleton @Memoized Supplier<List<Region>> regions(@UserProject Supplier<String> project,
- final GoogleComputeEngineApi api, AtomicReference<AuthorizationException> authException,
- @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
- return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier
- .create(authException, compose(new Function<String, List<Region>>() {
- public List<Region> apply(String project) {
- return ImmutableList.copyOf(concat(api.getRegionApi(project).list()));
- }
- }, project), seconds, TimeUnit.SECONDS);
- }
-
- @Provides @Singleton @Memoized Supplier<Map<URI, String>> selfLinkToNames(
- AtomicReference<AuthorizationException> authException, @Memoized Supplier<List<Region>> regions,
- @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
- return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier
- .create(authException, compose(new Function<List<Region>, Map<URI, String>>() {
- public Map<URI, String> apply(List<Region> regions) {
- ImmutableMap.Builder<URI, String> selfLinkToName = ImmutableMap.builder();
- for (Region region : regions) {
- selfLinkToName.put(region.selfLink(), region.name());
- for (URI zoneSelfLink : region.zones()) {
- selfLinkToName.put(zoneSelfLink, toName(zoneSelfLink));
- }
- }
- return selfLinkToName.build();
- }
- }, regions), seconds, TimeUnit.SECONDS);
- }
-
- static final class RegionIdToZoneIdsFromRegionList implements RegionIdToZoneIdsSupplier {
- private final Supplier<List<Region>> regions;
-
- @Inject RegionIdToZoneIdsFromRegionList(@Memoized Supplier<List<Region>> regions) {
- this.regions = regions;
- }
-
- @Override public Map<String, Supplier<Set<String>>> get() {
- ImmutableMap.Builder<String, Supplier<Set<String>>> result = ImmutableMap.builder();
- for (org.jclouds.googlecomputeengine.domain.Region region : regions.get()) {
- ImmutableSet.Builder<String> zoneIds = ImmutableSet.builder();
- for (URI uri : region.zones()) {
- zoneIds.add(toName(uri));
- }
- result.put(region.name(), Suppliers.<Set<String>>ofInstance(zoneIds.build()));
- }
- return result.build();
- }
- }
-
- static final class RegionIdToURISupplierFromRegionList implements RegionIdToURISupplier {
- private final Supplier<List<Region>> regions;
-
- @Inject RegionIdToURISupplierFromRegionList(@Memoized Supplier<List<Region>> regions) {
- this.regions = regions;
- }
-
- @Override public Map<String, Supplier<URI>> get() {
- ImmutableMap.Builder<String, Supplier<URI>> result = ImmutableMap.builder();
- for (org.jclouds.googlecomputeengine.domain.Region region : regions.get()) {
- result.put(region.name(), Suppliers.ofInstance(region.selfLink()));
- }
- return result.build();
- }
- }
-
- static final class ZoneIdToURIFromRegionList implements ZoneIdToURISupplier {
- private final Supplier<List<Region>> regions;
-
- @Inject ZoneIdToURIFromRegionList(@Memoized Supplier<List<Region>> regions) {
- this.regions = regions;
- }
-
- @Override public Map<String, Supplier<URI>> get() {
- ImmutableMap.Builder<String, Supplier<URI>> result = ImmutableMap.builder();
- for (Region region : regions.get()) {
- for (URI input : region.zones()) {
- result.put(toName(input), Suppliers.ofInstance(input));
- }
- }
- return result.build();
- }
- }
-
- private static String toName(URI link) {
- String path = link.getPath();
- return path.substring(path.lastIndexOf('/') + 1);
- }
-}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
index 815ccf1..892da57 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
@@ -19,6 +19,7 @@ package org.jclouds.googlecomputeengine.config;
import static org.jclouds.googlecomputeengine.domain.Firewall.Rule;
import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
@@ -26,12 +27,12 @@ import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.googlecomputeengine.domain.Firewall;
-import org.jclouds.googlecomputeengine.domain.Metadata;
-import org.jclouds.googlecomputeengine.domain.templates.InstanceTemplate;
+import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.googlecomputeengine.options.RouteOptions;
import org.jclouds.json.config.GsonModule;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
@@ -45,6 +46,7 @@ import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@@ -57,119 +59,13 @@ public final class GoogleComputeEngineParserModule extends AbstractModule {
@Provides @Singleton Map<Type, Object> typeAdapters() {
return new ImmutableMap.Builder<Type, Object>()
- .put(InstanceTemplate.class, new InstanceTemplateTypeAdapter())
.put(FirewallOptions.class, new FirewallOptionsTypeAdapter())
.put(RouteOptions.class, new RouteOptionsTypeAdapter()).build();
}
// TODO: change jclouds core to use collaborative set bindings
@Provides @Singleton Set<TypeAdapterFactory> typeAdapterFactories() {
- return ImmutableSet.<TypeAdapterFactory>of(new MetadataTypeAdapter());
- }
-
- private static final class InstanceTemplateTypeAdapter implements JsonSerializer<InstanceTemplate> {
-
- @Override public JsonElement serialize(InstanceTemplate src, Type typeOfSrc, JsonSerializationContext context) {
- InstanceTemplateInternal template = new InstanceTemplateInternal(src);
- JsonObject instance = (JsonObject) context.serialize(template, InstanceTemplateInternal.class);
-
- // deal with network
- JsonArray networkInterfaces = new JsonArray();
- for (InstanceTemplate.NetworkInterface networkInterface : template.networkInterfaces()) {
- networkInterfaces.add(context.serialize(networkInterface, InstanceTemplate.NetworkInterface.class));
- }
- instance.add("networkInterfaces", networkInterfaces);
-
- // deal with persistent disks
- if (!src.disks().isEmpty()) {
- instance.add("disks", context.serialize(src.disks()));
- }
-
- // deal with metadata
- if (!src.metadata().isEmpty()) {
- Metadata metadata = Metadata.create(null, src.metadata());
- JsonObject metadataJson = (JsonObject) context.serialize(metadata);
- instance.add("metadata", metadataJson);
- return instance;
- }
-
- return instance;
- }
-
- private static final class InstanceTemplateInternal extends InstanceTemplate {
- private InstanceTemplateInternal(InstanceTemplate template) {
- machineType(template.machineType());
- name(template.name());
- description(template.description());
- image(template.image());
- serviceAccounts(template.serviceAccounts());
- networkInterfaces(template.networkInterfaces());
- }
- }
- }
-
- private static final class MetadataTypeAdapter extends TypeAdapter<Metadata> implements TypeAdapterFactory {
-
- @Override public void write(JsonWriter out, Metadata src) throws IOException {
- out.beginObject();
- out.name("kind").value("compute#metadata");
- out.name("items");
- out.beginArray();
- for (Map.Entry<String, String> entry : src.items().entrySet()) {
- out.beginObject();
- out.name("key").value(entry.getKey());
- out.name("value").value(entry.getValue());
- out.endObject();
- }
- out.endArray();
- if (src.fingerprint() != null) {
- out.name("fingerprint").value(src.fingerprint());
- }
- out.endObject();
- }
-
- @Override public Metadata read(JsonReader in) throws IOException {
- String fingerprint = null;
- ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
- in.beginObject();
- while (in.hasNext()) {
- String name = in.nextName();
- if (name.equals("items")) {
- in.beginArray();
- while (in.hasNext()) {
- in.beginObject();
- String key = null;
- String value = null;
- while (in.hasNext()) {
- name = in.nextName();
- if (name.equals("key")) {
- key = in.nextString();
- } else if (name.equals("value")) {
- value = in.nextString();
- } else {
- in.skipValue();
- }
- }
- builder.put(key, value);
- in.endObject();
- }
- in.endArray();
- } else if (name.equals("fingerprint")) {
- fingerprint = in.nextString();
- } else {
- in.skipValue();
- }
- }
- in.endObject();
- return Metadata.create(fingerprint, builder.build());
- }
-
- @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
- if (!(Metadata.class.isAssignableFrom(typeToken.getRawType()))) {
- return null;
- }
- return (TypeAdapter<T>) this;
- }
+ return ImmutableSet.<TypeAdapterFactory>of(new ListPageAdapterFactory());
}
private static final class FirewallOptionsTypeAdapter implements JsonSerializer<FirewallOptions> {
@@ -247,4 +143,79 @@ public final class GoogleComputeEngineParserModule extends AbstractModule {
}
return array;
}
+
+ static final class ListPageAdapterFactory implements TypeAdapterFactory {
+ static final class ListPageAdapter extends TypeAdapter<ListPage<?>> {
+ private final TypeAdapter<?> itemAdapter;
+
+ ListPageAdapter(TypeAdapter<?> itemAdapter) {
+ this.itemAdapter = itemAdapter;
+ nullSafe();
+ }
+
+ public void write(JsonWriter out, ListPage<?> value) throws IOException {
+ throw new UnsupportedOperationException("We only read ListPages!");
+ }
+
+ public ListPage<?> read(JsonReader in) throws IOException {
+ ImmutableList.Builder<Object> items = ImmutableList.builder();
+ String nextPageToken = null;
+ in.beginObject();
+ while (in.hasNext()) {
+ String name = in.nextName();
+ if (name.equals("items")) {
+ if (in.peek() == JsonToken.BEGIN_ARRAY) {
+ readItems(in, items);
+ } else { // aggregated
+ readAggregate(in, items);
+ }
+ } else if (name.equals("nextPageToken")) {
+ nextPageToken = in.nextString();
+ } else {
+ in.skipValue();
+ }
+ }
+ in.endObject();
+ return ListPage.create(items.build(), nextPageToken);
+ }
+
+ private void readItems(JsonReader in, ImmutableList.Builder<Object> items) throws IOException {
+ in.beginArray();
+ while (in.hasNext()) {
+ Object item = itemAdapter.read(in);
+ if (item != null) {
+ items.add(item);
+ }
+ }
+ in.endArray();
+ }
+
+ private void readAggregate(JsonReader in, ImmutableList.Builder<Object> items) throws IOException {
+ in.beginObject(); // enter zone name -> type -> items map
+ while (in.hasNext()) {
+ String scope = in.nextName(); // skip zone name
+ in.beginObject(); // enter zone map
+ while (in.hasNext()) {
+ String resourceTypeOrWarning = in.nextName();
+ if (!resourceTypeOrWarning.equals("warning")) {
+ readItems(in, items);
+ } else {
+ in.skipValue();
+ }
+ }
+ in.endObject(); // end zone map
+ }
+ in.endObject(); // end item wrapper
+ }
+ }
+
+ @SuppressWarnings("unchecked") public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> ownerType) {
+ Type type = ownerType.getType();
+ if (ownerType.getRawType() != ListPage.class || !(type instanceof ParameterizedType))
+ return null;
+ Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
+ TypeAdapter<?> itemAdapter = gson.getAdapter(TypeToken.get(elementType));
+ return (TypeAdapter<T>) new ListPageAdapter(itemAdapter);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
index 19b55a8..25f39f0 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
@@ -16,27 +16,115 @@
*/
package org.jclouds.googlecomputeengine.domain;
-import static org.jclouds.googlecomputeengine.internal.NullSafeCopies.copyOf;
-
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.Map;
import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
-/** Metadata for an instance or project, with their fingerprint. */
+/**
+ * Metadata for an instance or project, with their fingerprint.
+ * <p/>
+ * This object is mutable and not thread-safe.
+ */
@AutoValue
-public abstract class Metadata {
+public abstract class Metadata implements Cloneable {
+
+ @AutoValue
+ abstract static class Entry {
+ abstract String key();
+
+ abstract String value();
+
+ @SerializedNames({ "key", "value" })
+ static Entry create(String key, String value) {
+ return new AutoValue_Metadata_Entry(key, value);
+ }
+ }
+
/** The fingerprint for the items - needed for updating them. */
@Nullable public abstract String fingerprint();
- public abstract Map<String, String> items();
+ /** Adds or replaces a metadata entry. */
+ public Metadata put(String key, String value) {
+ remove(key);
+ items().add(Entry.create(key, value));
+ return this;
+ }
+
+ /** Adds or replaces metadata entries. */
+ public Metadata putAll(Map<String, String> input) {
+ for (Map.Entry<String, String> entry : input.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ return this;
+ }
+
+ /** Removes any entry with the supplied key. */
+ public Metadata remove(String key) {
+ for (int i = 0, length = items().size(); i < length; i++) {
+ if (items().get(i).key().equals(key)) {
+ items().remove(i);
+ return this;
+ }
+ }
+ return this;
+ }
+
+ /** Copies the metadata into a new mutable map. */
+ public Map<String, String> asMap() {
+ Map<String, String> result = new LinkedHashMap<String, String>();
+ ArrayList<Entry> items = items();
+ for (int i = 0, length = items.size(); i < length; i++) {
+ Entry item = items.get(i);
+ result.put(item.key(), item.value());
+ }
+ return result;
+ }
- // No SerializedNames as custom-parsed.
- public static Metadata create(String fingerprint, Map<String, String> items) {
- return new AutoValue_Metadata(fingerprint, copyOf(items));
+ /** Returns the value with the supplied key, or null. */
+ @Nullable public String get(String key) {
+ ArrayList<Entry> items = items();
+ for (int i = 0, length = items.size(); i < length; i++) {
+ Entry item = items.get(i);
+ if (item.key().equals(key)) {
+ return item.value();
+ }
+ }
+ return null;
+ }
+
+ public boolean containsKey(String key) {
+ return get(key) != null;
+ }
+
+ public int size() {
+ return items().size();
+ }
+
+ /** Mutable list of metadata. */
+ abstract ArrayList<Entry> items();
+
+ public static Metadata create() {
+ return Metadata.create(null, null);
+ }
+
+ public static Metadata create(String fingerprint) {
+ return Metadata.create(fingerprint, null);
+ }
+
+ @SerializedNames({ "fingerprint", "items" })
+ static Metadata create(String fingerprint, ArrayList<Entry> items) { // Dictates the type when created from json!
+ return new AutoValue_Metadata(fingerprint, items != null ? items : new ArrayList<Entry>());
}
Metadata() {
}
+
+ @Override public Metadata clone() {
+ return Metadata.create(fingerprint(), new ArrayList<Entry>(items()));
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/NewInstance.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/NewInstance.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/NewInstance.java
new file mode 100644
index 0000000..73d3c4b
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/NewInstance.java
@@ -0,0 +1,157 @@
+/*
+ * 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 static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk.Type.PERSISTENT;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
+import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+/** Parameter to {@linkplain org.jclouds.googlecomputeengine.features.InstanceApi#create(NewInstance)}. */
+@AutoValue
+public abstract class NewInstance {
+ @AutoValue
+ abstract static class NetworkInterface {
+ abstract URI network();
+
+ abstract List<AccessConfig.Type> accessConfigs();
+
+ static NetworkInterface create(URI network) {
+ return create(network, Arrays.asList(AccessConfig.Type.ONE_TO_ONE_NAT));
+ }
+
+ @SerializedNames({ "network", "accessConfigs" })
+ static NetworkInterface create(URI network, List<AccessConfig.Type> accessConfigs) {
+ return new AutoValue_NewInstance_NetworkInterface(network, accessConfigs);
+ }
+
+ NetworkInterface() {
+ }
+ }
+
+ @AutoValue
+ public abstract static class Disk {
+ @AutoValue
+ abstract static class InitializeParams {
+ /** Override the default naming convention. */
+ @Nullable public abstract String diskName();
+
+ /** Set to use a size larger than the {@link #sourceImage()}. You need to repartition when set. */
+ @Nullable public abstract Long diskSizeGb();
+
+ /** The {@link org.jclouds.googlecomputeengine.domain.Image#selfLink() source image}. */
+ public abstract URI sourceImage();
+
+ static InitializeParams create(URI sourceImage) {
+ return create(null, null, sourceImage);
+ }
+
+ @SerializedNames({ "diskName", "diskSizeGb", "sourceImage" })
+ static InitializeParams create(String diskName, Long diskSizeGb, URI sourceImage) {
+ return new AutoValue_NewInstance_Disk_InitializeParams(diskName, diskSizeGb, sourceImage);
+ }
+
+ InitializeParams() {
+ }
+ }
+
+ public abstract AttachedDisk.Type type();
+
+ /** Use an existingBootDisk {@link org.jclouds.googlecomputeengine.domain.Disk#selfLink() boot disk}. */
+ @Nullable public abstract URI source();
+
+ /** Set to automatically create a boot disk */
+ @Nullable public abstract InitializeParams initializeParams();
+
+ public abstract boolean boot();
+
+ public abstract boolean autoDelete();
+
+ public static Disk existingBootDisk(URI existingBootDisk) {
+ return create(PERSISTENT, existingBootDisk, null, true, false);
+ }
+
+ public static Disk newBootDisk(URI sourceImage) {
+ return create(PERSISTENT, null, InitializeParams.create(sourceImage), true, true);
+ }
+
+ public static Disk existingDisk(URI existingDisk) {
+ return create(PERSISTENT, existingDisk, null, false, false);
+ }
+
+ @SerializedNames({ "type", "source", "initializeParams", "boot", "autoDelete" })
+ static Disk create(AttachedDisk.Type type, URI source, InitializeParams initializeParams, boolean boot,
+ boolean autoDelete) {
+ return new AutoValue_NewInstance_Disk(type, source, initializeParams, boot, autoDelete);
+ }
+
+ Disk() {
+ }
+ }
+
+ public abstract URI machineType();
+
+ public abstract String name();
+
+ public abstract List<NetworkInterface> networkInterfaces();
+
+ public abstract List<Disk> disks();
+
+ @Nullable public abstract String description();
+
+ public abstract Tags tags();
+
+ /** Add metadata via {@link Metadata#items()}. */
+ public abstract Metadata metadata();
+
+ public static NewInstance create(URI machineType, String name, URI network, Disk bootDisk, String description) {
+ return create(machineType, name, network, Arrays.asList(checkNotNull(bootDisk, "bootDisk")), description);
+ }
+
+ public static NewInstance create(URI machineType, String name, URI network, List<Disk> disks, String description) {
+ checkArgument(disks.get(0).boot(), "disk 0 must be a boot disk! %s", disks);
+ boolean foundBoot = false;
+ for (Disk disk : disks) {
+ if (disk.boot()) {
+ checkArgument(!foundBoot, "There must be only one boot disk! %s", disks);
+ foundBoot = true;
+ }
+ }
+ return create(machineType, name, ImmutableList.of(NetworkInterface.create(network)), ImmutableList.copyOf(disks),
+ description, Tags.create(), Metadata.create());
+ }
+
+ @SerializedNames({ "machineType", "name", "networkInterfaces", "disks", "description", "tags", "metadata" })
+ static NewInstance create(URI machineType, String name, List<NetworkInterface> networkInterfaces, List<Disk> disks,
+ String description, Tags tags, Metadata metadata) {
+ return new AutoValue_NewInstance(machineType, name, networkInterfaces, disks, description, tags, metadata);
+ }
+
+ NewInstance() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Tags.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Tags.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Tags.java
index cc1c880..23c7228 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Tags.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Tags.java
@@ -16,8 +16,7 @@
*/
package org.jclouds.googlecomputeengine.domain;
-import static org.jclouds.googlecomputeengine.internal.NullSafeCopies.copyOf;
-
+import java.util.ArrayList;
import java.util.List;
import org.jclouds.javax.annotation.Nullable;
@@ -25,19 +24,43 @@ import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
-/** Each tag must be unique, must be 1-63 characters long, and comply with RFC1035. */
+/**
+ * Tags for an instance or project, with their fingerprint. Each tag must be unique, must be 1-63 characters long, and
+ * comply with RFC1035.
+ * <p/>
+ * This object is mutable and not thread-safe.
+ */
@AutoValue
-public abstract class Tags {
+public abstract class Tags implements Cloneable {
/** The fingerprint for the items - needed for updating them. */
@Nullable public abstract String fingerprint();
+ /** Mutable list of tags. */
public abstract List<String> items();
+ /** Convenience method for chaining adds. */
+ public Tags add(String tag) {
+ items().add(tag);
+ return this;
+ }
+
+ public static Tags create() {
+ return Tags.create(null, null);
+ }
+
+ public static Tags create(String fingerprint) {
+ return Tags.create(fingerprint, null);
+ }
+
@SerializedNames({ "fingerprint", "items" })
- public static Tags create(String fingerprint, List<String> items) {
- return new AutoValue_Tags(fingerprint, copyOf(items));
+ static Tags create(String fingerprint, ArrayList<String> items) { // Dictates the type when created from json!
+ return new AutoValue_Tags(fingerprint, items != null ? items : new ArrayList<String>());
}
Tags() {
}
+
+ @Override public Tags clone() {
+ return Tags.create(fingerprint(), new ArrayList<String>(items()));
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/templates/InstanceTemplate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/templates/InstanceTemplate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/templates/InstanceTemplate.java
deleted file mode 100644
index c544453..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/templates/InstanceTemplate.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * 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.templates;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
-import static org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk.Mode;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import org.jclouds.googlecomputeengine.domain.Image;
-import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig;
-import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
-import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
-import org.jclouds.javax.annotation.Nullable;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/** Optional information for creating an instance. */
-// TODO! this is dangerously similarly named to the InstanceTemplate resource!
-public class InstanceTemplate {
-
- public static final class PersistentDisk {
-
- private final AttachedDisk.Type type = AttachedDisk.Type.PERSISTENT;
- private final AttachedDisk.Mode mode;
- private final URI source;
- private final String deviceName;
- private final boolean autoDelete;
- private final boolean boot;
-
- public PersistentDisk(AttachedDisk.Mode mode, URI source, String deviceName, boolean autoDelete, boolean boot) {
- this.mode = checkNotNull(mode, "mode");
- this.source = checkNotNull(source, "source");
- this.deviceName = deviceName;
- this.autoDelete = autoDelete;
- this.boot = boot;
- }
-
- public AttachedDisk.Mode mode() {
- return mode;
- }
-
- public URI source() {
- return source;
- }
-
- @Nullable public String deviceName() {
- return deviceName;
- }
-
- public boolean autoDelete() {
- return autoDelete;
- }
-
- public boolean boot() {
- return boot;
- }
- }
-
- public static final class NetworkInterface {
-
- private final URI network;
- private final String networkIP;
- private final List<AccessConfig> accessConfigs;
-
- public NetworkInterface(URI network, String networkIP, List<AccessConfig> accessConfigs) {
- this.network = network;
- this.networkIP = networkIP;
- this.accessConfigs = accessConfigs;
- }
-
- public URI network() {
- return network;
- }
-
- @Nullable public String networkIP() {
- return networkIP;
- }
-
- @Nullable public List<AccessConfig> accessConfigs() {
- return accessConfigs;
- }
- }
-
- private String name;
- private String description;
- private URI machineType;
- private URI image;
- private List<ServiceAccount> serviceAccounts = Lists.newArrayList();
- private List<PersistentDisk> disks = Lists.newArrayList();
- private List<NetworkInterface> networkInterfaces = Lists.newArrayList();
- private Map<String, String> metadata = Maps.newLinkedHashMap();
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#name()
- */
- public String name() {
- return name;
- }
-
- public InstanceTemplate name(String name) {
- this.name = name;
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#description()
- */
- public String description() {
- return description;
- }
-
- public InstanceTemplate description(String description) {
- this.description = description;
- return this;
- }
-
- /**
- * @see Image#selfLink()
- */
- public URI image() {
- return image;
- }
-
- public InstanceTemplate image(URI image) {
- this.image = image;
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#machineType()
- */
- public URI machineType() {
- return machineType;
- }
-
- public InstanceTemplate machineType(URI machineType) {
- this.machineType = machineType;
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#disks()
- */
- public List<PersistentDisk> disks() {
- return disks;
- }
-
- public InstanceTemplate addDisk(Mode mode, URI source) {
- this.disks.add(new PersistentDisk(mode, source, null, false, false));
- return this;
- }
-
- public InstanceTemplate addDisk(Mode mode, URI source, boolean autoDelete) {
- this.disks.add(new PersistentDisk(mode, source, null, autoDelete, false));
- return this;
- }
-
- public InstanceTemplate addDisk(Mode mode, URI source, String deviceName, boolean autoDelete) {
- this.disks.add(new PersistentDisk(mode, source, deviceName, autoDelete, false));
- return this;
- }
-
- public InstanceTemplate addDisk(Mode mode, URI source, String deviceName, boolean autoDelete, boolean boot) {
- this.disks.add(new PersistentDisk(mode, source, deviceName, autoDelete, boot));
- return this;
- }
-
- public InstanceTemplate disks(List<PersistentDisk> disks) {
- this.disks = Lists.newArrayList();
- this.disks.addAll(checkNotNull(disks, "disks"));
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#networkInterfaces()
- */
- public List<NetworkInterface> networkInterfaces() {
- return networkInterfaces;
- }
-
- public InstanceTemplate addNetworkInterface(URI network) {
- this.networkInterfaces.add(new NetworkInterface(network, null, null));
- return this;
- }
-
- public InstanceTemplate addNetworkInterface(URI network, Type type) {
- this.networkInterfaces
- .add(new NetworkInterface(network, null, ImmutableList.of(AccessConfig.create(null, type, null))));
- return this;
- }
-
- public InstanceTemplate addNetworkInterface(NetworkInterface networkInterface) {
- this.networkInterfaces.add(networkInterface);
- return this;
- }
-
- public InstanceTemplate networkInterfaces(List<NetworkInterface> networkInterfaces) {
- this.networkInterfaces = Lists.newArrayList(networkInterfaces);
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#metadata()
- */
- public Map<String, String> metadata() {
- return metadata;
- }
-
- public InstanceTemplate addMetadata(String key, String value) {
- this.metadata.put(checkNotNull(key, "key"), checkNotNull(value, "value of %", key));
- return this;
- }
-
- public InstanceTemplate metadata(Map<String, String> metadata) {
- this.metadata = Maps.newLinkedHashMap();
- this.metadata.putAll(checkNotNull(metadata, "metadata"));
- return this;
- }
-
- /**
- * @see org.jclouds.googlecomputeengine.domain.Instance#serviceAccounts()
- */
- public List<ServiceAccount> serviceAccounts() {
- return serviceAccounts;
- }
-
- public InstanceTemplate addServiceAccount(ServiceAccount serviceAccount) {
- this.serviceAccounts.add(checkNotNull(serviceAccount, "serviceAccount"));
- return this;
- }
-
- public InstanceTemplate serviceAccounts(List<ServiceAccount> serviceAccounts) {
- this.serviceAccounts = Lists.newArrayList();
- this.serviceAccounts.addAll(checkNotNull(serviceAccounts, "serviceAccounts"));
- return this;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AggregatedListApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AggregatedListApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AggregatedListApi.java
new file mode 100644
index 0000000..37a778a
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AggregatedListApi.java
@@ -0,0 +1,177 @@
+/*
+ * 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 static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+
+import java.util.Iterator;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.functions.internal.BaseToIteratorOfListPage;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.Json;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticationFilter.class)
+@Path("/aggregated")
+@Consumes(APPLICATION_JSON)
+public interface AggregatedListApi {
+
+ /**
+ * Retrieves the list of machine type 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 token marks the beginning of the next list page
+ * @param listOptions listing options
+ * @return a page of the list
+ */
+ @Named("MachineTypes:aggregatedList")
+ @GET
+ @Path("/machineTypes")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ ListPage<MachineType> pageOfMachineTypes(@Nullable @QueryParam("pageToken") String token, ListOptions listOptions);
+
+ /**
+ * @see #pageOfMachineTypes(String, ListOptions)
+ */
+ @Named("MachineTypes:aggregatedList")
+ @GET
+ @Path("/machineTypes")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(MachineTypePage.class)
+ @Transform(MachineTypePages.class)
+ Iterator<ListPage<MachineType>> machineTypes();
+
+ /**
+ * @see #pageOfMachineTypes(String, ListOptions)
+ */
+ @Named("MachineTypes:aggregatedList")
+ @GET
+ @Path("/machineTypes")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(MachineTypePage.class)
+ @Transform(MachineTypePages.class)
+ Iterator<ListPage<MachineType>> machineTypes(ListOptions options);
+
+ static final class MachineTypePage extends ParseJson<ListPage<MachineType>> {
+ @Inject MachineTypePage(Json json) {
+ super(json, new TypeLiteral<ListPage<MachineType>>() {
+ });
+ }
+ }
+
+ static final class MachineTypePages extends BaseToIteratorOfListPage<MachineType, MachineTypePages> {
+ private final GoogleComputeEngineApi api;
+
+ @Inject MachineTypePages(GoogleComputeEngineApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<String, ListPage<MachineType>> fetchNextPage(final String project, final ListOptions options) {
+ return new Function<String, ListPage<MachineType>>() {
+ @Override public ListPage<MachineType> apply(String input) {
+ return api.aggregatedList(project).pageOfMachineTypes(input, options);
+ }
+ };
+ }
+ }
+
+ /**
+ * 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 token marks the beginning of the next list page
+ * @param listOptions listing options
+ * @return a page of the list
+ */
+ @Named("Instances:aggregatedList")
+ @GET
+ @Path("/instances")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ ListPage<Instance> pageOfInstances(@Nullable @QueryParam("pageToken") String token, ListOptions listOptions);
+
+ /**
+ * @see #pageOfInstances(String, ListOptions)
+ */
+ @Named("Instances:aggregatedList")
+ @GET
+ @Path("/instances")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(InstancePage.class)
+ @Transform(InstancePages.class)
+ Iterator<ListPage<Instance>> instances();
+
+ /**
+ * @see #pageOfInstances(String, ListOptions)
+ */
+ @Named("Instances:aggregatedList")
+ @GET
+ @Path("/instances")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(InstancePage.class)
+ @Transform(InstancePages.class)
+ Iterator<ListPage<Instance>> instances(ListOptions options);
+
+ static final class InstancePage extends ParseJson<ListPage<Instance>> {
+ @Inject InstancePage(Json json) {
+ super(json, new TypeLiteral<ListPage<Instance>>() {
+ });
+ }
+ }
+
+ static final class InstancePages extends BaseToIteratorOfListPage<Instance, InstancePages> {
+ private final GoogleComputeEngineApi api;
+
+ @Inject InstancePages(GoogleComputeEngineApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<String, ListPage<Instance>> fetchNextPage(final String project, final ListOptions options) {
+ return new Function<String, ListPage<Instance>>() {
+ @Override public ListPage<Instance> apply(String input) {
+ return api.aggregatedList(project).pageOfInstances(input, options);
+ }
+ };
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
index 17ec3e8..5c107fa 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
@@ -23,7 +23,6 @@ import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.A
import static org.jclouds.googlecomputeengine.domain.Instance.SerialPortOutput;
import java.util.Iterator;
-import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
@@ -38,11 +37,11 @@ import javax.ws.rs.QueryParam;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.googlecomputeengine.GoogleComputeEngineFallbacks.EmptyIteratorOnNotFoundOr404;
import org.jclouds.googlecomputeengine.GoogleComputeEngineFallbacks.EmptyListPageOnNotFoundOr404;
-import org.jclouds.googlecomputeengine.binders.MetadataBinder;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Metadata;
+import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.googlecomputeengine.domain.templates.InstanceTemplate;
import org.jclouds.googlecomputeengine.functions.internal.ParseInstances;
import org.jclouds.googlecomputeengine.options.AttachDiskOptions;
import org.jclouds.googlecomputeengine.options.ListOptions;
@@ -85,7 +84,7 @@ public interface InstanceApi {
@POST
@Produces(APPLICATION_JSON)
@OAuthScopes(COMPUTE_SCOPE)
- Operation create(@BinderParam(BindToJsonPayload.class) InstanceTemplate template);
+ Operation create(@BinderParam(BindToJsonPayload.class) NewInstance template);
/** Deletes an instance by name and returns the operation in progress, or null if not found. */
@Named("Instances:delete")
@@ -231,17 +230,15 @@ public interface InstanceApi {
* Sets metadata for an instance using the data included in the request.
* <p/>
* NOTE: This *sets* metadata items on the project (vs *adding* items to metadata),
- * if there are pre-existing metadata items that must be kept these must be fetched first and then re-set on the
- * new Metadata, e.g.
+ * if there are existing metadata that must be kept these must be fetched first and then re-sent on update.
* <pre><tt>
- * Metadata.Builder current = instanceApi.get("us-central1-a", "myInstance").getMetadata().toBuilder();
- * current.addItem("newItem","newItemValue");
- * instanceApi.setMetadata("us-central1-a", "myInstance", current.build());
+ * Metadata update = instanceApi.get("myInstance").metadata().clone();
+ * update.put("newItem","newItemValue");
+ * instanceApi.setMetadata("myInstance", update);
* </tt></pre>
*
* @param instance The name of the instance
* @param metadata the metadata to set
- * @param fingerprint The current fingerprint for the items
*
* @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
* to you, and look for the status field.
@@ -251,10 +248,8 @@ public interface InstanceApi {
@Path("/{instance}/setMetadata")
@OAuthScopes(COMPUTE_SCOPE)
@Produces(APPLICATION_JSON)
- @MapBinder(MetadataBinder.class)
Operation setMetadata(@PathParam("instance") String instance,
- @PayloadParam("items") Map<String, String> metadata,
- @PayloadParam("fingerprint") String fingerprint);
+ @BinderParam(BindToJsonPayload.class) Metadata metadata);
/**
* Lists items for an instance
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
index 2a9c1a1..cc10657 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
@@ -20,8 +20,6 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import java.util.Map;
-
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -31,16 +29,16 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.jclouds.googlecomputeengine.GoogleComputeEngineFallbacks.NullOn400or404;
-import org.jclouds.googlecomputeengine.binders.MetadataBinder;
+import org.jclouds.googlecomputeengine.domain.Metadata;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
+import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.binders.BindToJsonPayload;
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticationFilter.class)
@@ -60,17 +58,15 @@ public interface ProjectApi {
* Sets metadata common to all instances within the specified project using the data included in the request.
* <p/>
* NOTE: This *sets* metadata items on the project (vs *adding* items to metadata),
- * if there are pre-existing metadata items that must be kept these must be fetched first and then re-set on the
- * new Metadata, e.g.
+ * if there are existing metadata that must be kept these must be fetched first and then re-sent on update.
* <pre><tt>
- * Metadata.Builder current = projectApi.get("myProject").getCommonInstanceMetadata().toBuilder();
- * current.addItem("newItem","newItemValue");
- * projectApi.setCommonInstanceMetadata(current.build());
+ * Metadata update = projectApi.get("myProject").getCommonInstanceMetadata().clone();
+ * update.put("newItem","newItemValue");
+ * projectApi.setCommonInstanceMetadata("myProject", update);
* </tt></pre>
*
- * @param projectName name of the project to return
- * @param metadata the metadata to set
- * @param fingerprint The current fingerprint for the metadata
+ * @param projectName name of the project to return
+ * @param metadata the metadata to set
* @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
* to you, and look for the status field.
*/
@@ -79,8 +75,6 @@ public interface ProjectApi {
@Path("/{project}/setCommonInstanceMetadata")
@OAuthScopes(COMPUTE_SCOPE)
@Produces(APPLICATION_JSON)
- @MapBinder(MetadataBinder.class)
Operation setCommonInstanceMetadata(@PathParam("project") String projectName,
- @PayloadParam("items") Map<String, String> metadata,
- @PayloadParam("fingerprint") String fingerprint);
+ @BinderParam(BindToJsonPayload.class) Metadata metadata);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToIteratorOfListPage.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToIteratorOfListPage.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToIteratorOfListPage.java
index 66b9d75..ec07bb5 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToIteratorOfListPage.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToIteratorOfListPage.java
@@ -20,7 +20,6 @@ import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.tryFind;
import java.util.Iterator;
-import java.util.List;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
@@ -34,7 +33,7 @@ import com.google.common.base.Optional;
import com.google.common.collect.Iterators;
@Beta
-abstract class BaseToIteratorOfListPage<T, I extends BaseToIteratorOfListPage<T, I>>
+public abstract class BaseToIteratorOfListPage<T, I extends BaseToIteratorOfListPage<T, I>>
implements Function<ListPage<T>, Iterator<ListPage<T>>>, InvocationContext<I> {
private GeneratedHttpRequest request;
@@ -42,18 +41,13 @@ abstract class BaseToIteratorOfListPage<T, I extends BaseToIteratorOfListPage<T,
@Override
public Iterator<ListPage<T>> apply(ListPage<T> input) {
if (input.nextPageToken() == null) {
- return Iterators.singletonIterator(input);
+ return input.isEmpty() ? Iterators.<ListPage<T>>emptyIterator() : Iterators.singletonIterator(input);
}
- List<Object> callerArgs = request.getCaller().get().getArgs();
-
- assert callerArgs.size() == 1 : String.format("programming error, method %s should have 1 arg: project",
- request.getCaller().get().getInvokable());
-
Optional<Object> listOptions = tryFind(request.getInvocation().getArgs(), instanceOf(ListOptions.class));
return new AdvancingIterator<T>(input,
- fetchNextPage((String) callerArgs.get(0), (ListOptions) listOptions.orNull()));
+ fetchNextPage((String) request.getCaller().get().getArgs().get(0), (ListOptions) listOptions.orNull()));
}
protected abstract Function<String, ListPage<T>> fetchNextPage(String projectName, ListOptions listOptions);
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6b5643c9/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/binders/ForwardingRuleCreationBinderTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/binders/ForwardingRuleCreationBinderTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/binders/ForwardingRuleCreationBinderTest.java
index 3a480d8..d45a6c3 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/binders/ForwardingRuleCreationBinderTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/binders/ForwardingRuleCreationBinderTest.java
@@ -38,8 +38,7 @@ public class ForwardingRuleCreationBinderTest extends BaseGoogleComputeEngineExp
private static String DESCRIPTION = "This is a test!";
private static String IP_ADDRESS = "1.2.1.1.1";
private static String PORT_RANGE = "1.2.3.4.1";
- private static URI TARGET = URI.create("https://www.googleapis.com/compute/v1/projects/myproject/regions/"
- + "europe-west1/targetPools/test-target-pool");
+ private static URI TARGET = URI.create(BASE_URL + "/party/regions/europe-west1/targetPools/test-target-pool");
Json json = new GsonWrapper(new Gson());