You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/07/29 19:36:49 UTC

[5/8] JCLOUDS-192. Move GCE to API v1beta15 - no new APIs added other than Zone/GlobalOperations, which are needed for zone-scoping changes.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneOperationApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneOperationApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneOperationApi.java
new file mode 100644
index 0000000..e96bd6e
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneOperationApi.java
@@ -0,0 +1,164 @@
+/*
+ * 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.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.functions.internal.ParseZoneOperations;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.Transform;
+
+/**
+ * Provides access to Operations via their REST API.
+ *
+ * @author David Alves
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/operations"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+public interface ZoneOperationApi {
+
+   /**
+    * Retrieves the specified operation resource.
+    *
+    * @param zone          the zone the operation is in
+    * @param operationName name of the operation resource to return.
+    * @return If successful, this method returns an Operation resource
+    */
+   @Named("ZoneOperations:get")
+   @GET
+   @Path("/zones/{zone}/operations/{operation}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   Operation getInZone(@PathParam("zone") String zone, @PathParam("operation") String operationName);
+
+   /**
+    * Deletes the specified operation resource.
+    *
+    * @param zone          the zone the operation is in
+    * @param operationName name of the operation resource to delete.
+    */
+   @Named("ZoneOperations:delete")
+   @DELETE
+   @Path("/zones/{zone}/operations/{operation}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   void deleteInZone(@PathParam("zone") String zone, @PathParam("operation") String operationName);
+
+   /**
+    * @see ZoneOperationApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("ZoneOperations:list")
+   @GET
+   @Path("/zones/{zone}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseZoneOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listFirstPageInZone(@PathParam("zone") String zone);
+
+   /**
+    * @see ZoneOperationApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("ZoneOperations:list")
+   @GET
+   @Path("/zones/{zone}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseZoneOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarkerInZone(@PathParam("zone") String zone,
+                                          @QueryParam("pageToken") @Nullable String marker);
+
+   /**
+    * Retrieves the listFirstPage of operation resources contained within the specified project.
+    * By default the listFirstPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults()
+    * has not been set.
+    *
+    * @param zone        the zone to list in
+    * @param marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the list, starting at marker
+    * @see ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("ZoneOperations:list")
+   @GET
+   @Path("/zones/{zone}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseZoneOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarkerInZone(@PathParam("zone") String zone,
+                                          @QueryParam("pageToken") @Nullable String marker,
+                                          ListOptions listOptions);
+
+   /**
+    * @see ZoneOperationApi#listInZone(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("ZoneOperations:list")
+   @GET
+   @Path("/zones/{zone}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseZoneOperations.class)
+   @Transform(ParseZoneOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> listInZone(@PathParam("zone") String zone);
+
+   /**
+    * A paged version of ZoneOperationApi#listFirstPageInZone(String)
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see PagedIterable
+    * @see ZoneOperationApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("ZoneOperations:list")
+   @GET
+   @Path("/zones/{zone}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseZoneOperations.class)
+   @Transform(ParseZoneOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> listInZone(@PathParam("zone") String zone, ListOptions listOptions);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToPagedIterable.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToPagedIterable.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToPagedIterable.java
index 8542a37..cc3142b 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToPagedIterable.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseToPagedIterable.java
@@ -16,9 +16,9 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
+import static com.google.common.base.Predicates.instanceOf;
+import static com.google.common.collect.Iterables.tryFind;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.collect.PagedIterables;
@@ -28,15 +28,16 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.rest.InvocationContext;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
 
-import static com.google.common.base.Predicates.instanceOf;
-import static com.google.common.collect.Iterables.tryFind;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
 
 /**
  * @author Adrian Cole
  */
 @Beta
 public abstract class BaseToPagedIterable<T, I extends BaseToPagedIterable<T, I>> implements
-      Function<ListPage<T>, PagedIterable<T>>, InvocationContext<I> {
+        Function<ListPage<T>, PagedIterable<T>>, InvocationContext<I> {
 
    private GeneratedHttpRequest request;
 
@@ -50,7 +51,7 @@ public abstract class BaseToPagedIterable<T, I extends BaseToPagedIterable<T, I>
       Optional<Object> listOptions = tryFind(request.getInvocation().getArgs(), instanceOf(ListOptions.class));
 
       assert project.isPresent() : String.format("programming error, method %s should have a string param for the "
-            + "project", request.getCaller().get().getInvokable());
+              + "project", request.getCaller().get().getInvokable());
 
       return PagedIterables.advance(
               input, fetchNextPage(project.get().toString(), (ListOptions) listOptions.orNull()));

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithZoneToPagedIterable.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithZoneToPagedIterable.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithZoneToPagedIterable.java
new file mode 100644
index 0000000..0c17488
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithZoneToPagedIterable.java
@@ -0,0 +1,76 @@
+/*
+ * 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.functions.internal;
+
+import static com.google.common.base.Predicates.instanceOf;
+import static com.google.common.collect.Iterables.tryFind;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.PagedIterables;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.InvocationContext;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+
+/**
+ * @author Adrian Cole
+ * @author Andrew Bayer
+ */
+@Beta
+public abstract class BaseWithZoneToPagedIterable<T, I extends BaseWithZoneToPagedIterable<T, I>> implements
+        Function<ListPage<T>, PagedIterable<T>>, InvocationContext<I> {
+
+   private GeneratedHttpRequest request;
+
+   @Override
+   public PagedIterable<T> apply(ListPage<T> input) {
+      if (input.nextMarker() == null)
+         return PagedIterables.of(input);
+
+      Optional<Object> project = tryFind(request.getCaller().get().getArgs(), instanceOf(String.class));
+
+      Optional<Object> zone = tryFind(request.getCaller().get().getArgs(), instanceOf(String.class));
+
+      Optional<Object> listOptions = tryFind(request.getInvocation().getArgs(), instanceOf(ListOptions.class));
+
+      assert project.isPresent() : String.format("programming error, method %s should have a string param for the "
+              + "project", request.getCaller().get().getInvokable());
+
+      assert zone.isPresent() : String.format("programming error, method %s should have a string param for the "
+              + "zone", request.getCaller().get().getInvokable());
+
+      return PagedIterables.advance(
+              input, fetchNextPage(project.get().toString(), zone.get().toString(), (ListOptions) listOptions.orNull()));
+   }
+
+   protected abstract Function<Object, IterableWithMarker<T>> fetchNextPage(String projectName,
+                                                                            String zoneName,
+                                                                            ListOptions listOptions);
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public I setContext(HttpRequest request) {
+      this.request = GeneratedHttpRequest.class.cast(request);
+      return (I) this;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/PATCH.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/PATCH.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/PATCH.java
index 70875bf..04d9138 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/PATCH.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/PATCH.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import javax.ws.rs.HttpMethod;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import javax.ws.rs.HttpMethod;
+
 /**
  * Indicates that the annotated method responds to HTTP PATCH requests
  *

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseDisks.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseDisks.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseDisks.java
index 18bb6ba..13e1946 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseDisks.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseDisks.java
@@ -16,8 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Disk;
@@ -26,10 +29,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -39,10 +40,11 @@ public class ParseDisks extends ParseJson<ListPage<Disk>> {
 
    @Inject
    public ParseDisks(Json json) {
-      super(json, new TypeLiteral<ListPage<Disk>>() {});
+      super(json, new TypeLiteral<ListPage<Disk>>() {
+      });
    }
 
-   public static class ToPagedIterable extends BaseToPagedIterable<Disk, ToPagedIterable> {
+   public static class ToPagedIterable extends BaseWithZoneToPagedIterable<Disk, ToPagedIterable> {
 
       private final GoogleComputeEngineApi api;
 
@@ -53,12 +55,14 @@ public class ParseDisks extends ParseJson<ListPage<Disk>> {
 
       @Override
       protected Function<Object, IterableWithMarker<Disk>> fetchNextPage(final String projectName,
+                                                                         final String zoneName,
                                                                          final ListOptions options) {
          return new Function<Object, IterableWithMarker<Disk>>() {
 
             @Override
             public IterableWithMarker<Disk> apply(Object input) {
-               return api.getDiskApiForProject(projectName).listAtMarker(input.toString(), options);
+               return api.getDiskApiForProject(projectName)
+                       .listAtMarkerInZone(zoneName, input.toString(), options);
             }
          };
       }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseFirewalls.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseFirewalls.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseFirewalls.java
index 6b977e4..41181ac 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseFirewalls.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseFirewalls.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Firewall;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,7 +38,8 @@ public class ParseFirewalls extends ParseJson<ListPage<Firewall>> {
 
    @Inject
    public ParseFirewalls(Json json) {
-      super(json, new TypeLiteral<ListPage<Firewall>>() {});
+      super(json, new TypeLiteral<ListPage<Firewall>>() {
+      });
    }
 
    public static class ToPagedIterable extends BaseToPagedIterable<Firewall, ToPagedIterable> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseGlobalOperations.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseGlobalOperations.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseGlobalOperations.java
new file mode 100644
index 0000000..bee5c28
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseGlobalOperations.java
@@ -0,0 +1,66 @@
+/*
+ * 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.functions.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author David Alves
+ */
+public class ParseGlobalOperations extends ParseJson<ListPage<Operation>> {
+
+   @Inject
+   public ParseGlobalOperations(Json json) {
+      super(json, new TypeLiteral<ListPage<Operation>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseToPagedIterable<Operation, ToPagedIterable> {
+
+      private final GoogleComputeEngineApi api;
+
+      @Inject
+      protected ToPagedIterable(GoogleComputeEngineApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      @Override
+      protected Function<Object, IterableWithMarker<Operation>> fetchNextPage(final String projectName,
+                                                                              final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Operation>>() {
+
+            @Override
+            public IterableWithMarker<Operation> apply(Object input) {
+               return api.getGlobalOperationApiForProject(projectName).listAtMarker(input.toString(), options);
+            }
+         };
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseImages.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseImages.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseImages.java
index 75bbb33..df28631 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseImages.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseImages.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Image;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,7 +38,8 @@ public class ParseImages extends ParseJson<ListPage<Image>> {
 
    @Inject
    public ParseImages(Json json) {
-      super(json, new TypeLiteral<ListPage<Image>>() {});
+      super(json, new TypeLiteral<ListPage<Image>>() {
+      });
    }
 
    public static class ToPagedIterable extends BaseToPagedIterable<Image, ToPagedIterable> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseInstances.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseInstances.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseInstances.java
index 638d916..b063e80 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseInstances.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseInstances.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Instance;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,10 +38,11 @@ public class ParseInstances extends ParseJson<ListPage<Instance>> {
 
    @Inject
    public ParseInstances(Json json) {
-      super(json, new TypeLiteral<ListPage<Instance>>() {});
+      super(json, new TypeLiteral<ListPage<Instance>>() {
+      });
    }
 
-   public static class ToPagedIterable extends BaseToPagedIterable<Instance, ToPagedIterable> {
+   public static class ToPagedIterable extends BaseWithZoneToPagedIterable<Instance, ToPagedIterable> {
 
       private final GoogleComputeEngineApi api;
 
@@ -50,13 +52,15 @@ public class ParseInstances extends ParseJson<ListPage<Instance>> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Instance>> fetchNextPage(final String projectName,
+      protected Function<Object, IterableWithMarker<Instance>> fetchNextPage(final String project,
+                                                                             final String zone,
                                                                              final ListOptions options) {
          return new Function<Object, IterableWithMarker<Instance>>() {
 
             @Override
             public IterableWithMarker<Instance> apply(Object input) {
-               return api.getInstanceApiForProject(projectName).listAtMarker(input.toString(), options);
+               return api.getInstanceApiForProject(project)
+                       .listAtMarkerInZone(zone, input.toString(), options);
             }
          };
       }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseKernels.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseKernels.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseKernels.java
index 9f181a4..121677f 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseKernels.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseKernels.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Kernel;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,7 +38,8 @@ public class ParseKernels extends ParseJson<ListPage<Kernel>> {
 
    @Inject
    public ParseKernels(Json json) {
-      super(json, new TypeLiteral<ListPage<Kernel>>() {});
+      super(json, new TypeLiteral<ListPage<Kernel>>() {
+      });
    }
 
    public static class ToPagedIterable extends BaseToPagedIterable<Kernel, ToPagedIterable> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseMachineTypes.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseMachineTypes.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseMachineTypes.java
index 3db1519..e18b5c4 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseMachineTypes.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseMachineTypes.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.ListPage;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -40,7 +41,7 @@ public class ParseMachineTypes extends ParseJson<ListPage<MachineType>> {
       super(json, new TypeLiteral<ListPage<MachineType>>() {});
    }
 
-   public static class ToPagedIterable extends BaseToPagedIterable<MachineType, ToPagedIterable> {
+   public static class ToPagedIterable extends BaseWithZoneToPagedIterable<MachineType, ToPagedIterable> {
 
       private final GoogleComputeEngineApi api;
 
@@ -50,13 +51,15 @@ public class ParseMachineTypes extends ParseJson<ListPage<MachineType>> {
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<MachineType>> fetchNextPage(final String projectName,
+      protected Function<Object, IterableWithMarker<MachineType>> fetchNextPage(final String project,
+                                                                                final String zone,
                                                                                 final ListOptions options) {
          return new Function<Object, IterableWithMarker<MachineType>>() {
 
             @Override
             public IterableWithMarker<MachineType> apply(Object input) {
-               return api.getMachineTypeApiForProject(projectName).listAtMarker(input.toString(), options);
+               return api.getMachineTypeApiForProject(project)
+                       .listAtMarkerInZone(zone, input.toString(), options);
             }
          };
       }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseNetworks.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseNetworks.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseNetworks.java
index 195e162..aad984b 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseNetworks.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseNetworks.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.ListPage;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,7 +38,8 @@ public class ParseNetworks extends ParseJson<ListPage<Network>> {
 
    @Inject
    public ParseNetworks(Json json) {
-      super(json, new TypeLiteral<ListPage<Network>>() {});
+      super(json, new TypeLiteral<ListPage<Network>>() {
+      });
    }
 
    public static class ToPagedIterable extends BaseToPagedIterable<Network, ToPagedIterable> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseOperations.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseOperations.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseOperations.java
deleted file mode 100644
index 3749a2f..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseOperations.java
+++ /dev/null
@@ -1,64 +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.functions.internal;
-
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
-import org.jclouds.googlecomputeengine.domain.ListPage;
-import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.googlecomputeengine.options.ListOptions;
-import org.jclouds.http.functions.ParseJson;
-import org.jclouds.json.Json;
-
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * @author David Alves
- */
-public class ParseOperations extends ParseJson<ListPage<Operation>> {
-
-   @Inject
-   public ParseOperations(Json json) {
-      super(json, new TypeLiteral<ListPage<Operation>>() {});
-   }
-
-   public static class ToPagedIterable extends BaseToPagedIterable<Operation, ToPagedIterable> {
-
-      private final GoogleComputeEngineApi api;
-
-      @Inject
-      protected ToPagedIterable(GoogleComputeEngineApi api) {
-         this.api = checkNotNull(api, "api");
-      }
-
-      @Override
-      protected Function<Object, IterableWithMarker<Operation>> fetchNextPage(final String projectName,
-                                                                              final ListOptions options) {
-         return new Function<Object, IterableWithMarker<Operation>>() {
-
-            @Override
-            public IterableWithMarker<Operation> apply(Object input) {
-               return api.getOperationApiForProject(projectName).listAtMarker(input.toString(), options);
-            }
-         };
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZoneOperations.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZoneOperations.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZoneOperations.java
new file mode 100644
index 0000000..11431af
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZoneOperations.java
@@ -0,0 +1,68 @@
+/*
+ * 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.functions.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author David Alves
+ */
+public class ParseZoneOperations extends ParseJson<ListPage<Operation>> {
+
+   @Inject
+   public ParseZoneOperations(Json json) {
+      super(json, new TypeLiteral<ListPage<Operation>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseWithZoneToPagedIterable<Operation, ToPagedIterable> {
+
+      private final GoogleComputeEngineApi api;
+
+      @Inject
+      protected ToPagedIterable(GoogleComputeEngineApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      @Override
+      protected Function<Object, IterableWithMarker<Operation>> fetchNextPage(final String projectName,
+                                                                              final String zoneName,
+                                                                              final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Operation>>() {
+
+            @Override
+            public IterableWithMarker<Operation> apply(Object input) {
+               return api.getZoneOperationApiForProject(projectName)
+                       .listAtMarkerInZone(zoneName, input.toString(), options);
+            }
+         };
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZones.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZones.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZones.java
index dd640bd..76aa158 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZones.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseZones.java
@@ -16,8 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.functions.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.TypeLiteral;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.ListPage;
@@ -26,9 +28,8 @@ import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 
-import javax.inject.Inject;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
@@ -37,7 +38,8 @@ public class ParseZones extends ParseJson<ListPage<Zone>> {
 
    @Inject
    public ParseZones(Json json) {
-      super(json, new TypeLiteral<ListPage<Zone>>() {});
+      super(json, new TypeLiteral<ListPage<Zone>>() {
+      });
    }
 
    public static class ToPagedIterable extends BaseToPagedIterable<Zone, ToPagedIterable> {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/FirewallBinder.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/FirewallBinder.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/FirewallBinder.java
index da53104..6c3b8b8 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/FirewallBinder.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/FirewallBinder.java
@@ -16,16 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
-import org.jclouds.googlecomputeengine.options.FirewallOptions;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.MapBinder;
-import org.jclouds.rest.binders.BindToJsonPayload;
+import static com.google.common.base.Preconditions.checkNotNull;
 
-import javax.inject.Inject;
 import java.net.URI;
 import java.util.Map;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import javax.inject.Inject;
+
+import org.jclouds.googlecomputeengine.options.FirewallOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandler.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandler.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandler.java
index ed2dc2f..4324c01 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandler.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandler.java
@@ -16,6 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import javax.inject.Singleton;
+
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.HttpResponse;
@@ -23,10 +27,6 @@ import org.jclouds.http.HttpResponseException;
 import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ResourceNotFoundException;
 
-import javax.inject.Singleton;
-
-import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
-
 /**
  * This will parse and set an appropriate exception on the command object.
  *

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/InstanceBinder.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/InstanceBinder.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/InstanceBinder.java
index ae73d9c..c221969 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/InstanceBinder.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/InstanceBinder.java
@@ -16,18 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
-import com.google.common.base.Function;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
 import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.rest.MapBinder;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.net.URI;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
 
 /**
  * @author David Alves
@@ -38,13 +40,9 @@ public class InstanceBinder implements MapBinder {
    private BindToJsonPayload jsonBinder;
 
    @Inject
-   @Named("machineTypes")
+   @Named("machineTypeToURI")
    Function<String, URI> machineTypesToURI;
 
-   @Inject
-   @Named("zones")
-   Function<String, URI> zonesToURI;
-
    /**
     * {@inheritDoc}
     */
@@ -52,12 +50,10 @@ public class InstanceBinder implements MapBinder {
    public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
       InstanceTemplate template = (InstanceTemplate) checkNotNull(postParams.get("template"), "template");
       template.name(checkNotNull(postParams.get("name"), "name").toString());
-      template.zone(zonesToURI.apply((String) checkNotNull(postParams.get("zone"), "zone")));
 
       if (template.getMachineTypeName() != null) {
          template.machineType(machineTypesToURI.apply(template.getMachineTypeName()));
       }
-      template.zone((String) null);
       template.machineType((String) null);
       return bindToRequest(request, template);
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/MetadataBinder.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/MetadataBinder.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/MetadataBinder.java
index f741d08..0230088 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/MetadataBinder.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/MetadataBinder.java
@@ -16,16 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
 import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.rest.Binder;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
-import javax.inject.Inject;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 /**
  * @author David Alves
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/AttachDiskOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/AttachDiskOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/AttachDiskOptions.java
new file mode 100644
index 0000000..fd01448
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/AttachDiskOptions.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.options;
+
+import java.net.URI;
+
+/**
+ * Options for attaching disks to instances.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/instances/attachDisk"/>
+ */
+public class AttachDiskOptions {
+
+   public enum DiskType {
+      SCRATCH,
+      PERSISTENT
+   }
+
+   public enum DiskMode {
+      READ_WRITE,
+      READ_ONLY
+   }
+
+   private DiskType type;
+   private DiskMode mode;
+   private URI source;
+   private String deviceName;
+
+   /**
+    * The disk type
+    *
+    * @return the disk type.
+    */
+   public DiskType getType() {
+      return type;
+   }
+
+   /**
+    * The disk mode
+    *
+    * @return the disk mode
+    */
+   public DiskMode getMode() {
+      return mode;
+   }
+
+   /**
+    * The URI of the source disk - optional, if DiskType.SCRATCH is used.
+    *
+    * @return the URI
+    */
+   public URI getSource() {
+      return source;
+   }
+
+   /**
+    * The device name on the instance - optional.
+    *
+    * @return the device name
+    */
+   public String getDeviceName() {
+      return deviceName;
+   }
+
+
+   /**
+    * @see AttachDiskOptions#getType()
+    */
+   public AttachDiskOptions type(DiskType type) {
+      this.type = type;
+      return this;
+   }
+
+   /**
+    * @see AttachDiskOptions#getMode()
+    */
+   public AttachDiskOptions mode(DiskMode mode) {
+      this.mode = mode;
+      return this;
+   }
+
+   /**
+    * @see AttachDiskOptions#getSource()
+    */
+   public AttachDiskOptions source(URI source) {
+      this.source = source;
+      return this;
+   }
+
+   /**
+    * @see AttachDiskOptions#getDeviceName()
+    */
+   public AttachDiskOptions deviceName(String deviceName) {
+      this.deviceName = deviceName;
+      return this;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/FirewallOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/FirewallOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/FirewallOptions.java
index cf1c022..6c049e2 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/FirewallOptions.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/FirewallOptions.java
@@ -16,17 +16,18 @@
  */
 package org.jclouds.googlecomputeengine.options;
 
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.googlecomputeengine.domain.Firewall;
-
 import java.net.URI;
 import java.util.Set;
 
+import org.jclouds.googlecomputeengine.domain.Firewall;
+
+import com.google.common.collect.ImmutableSet;
+
 /**
  * Options to create a firewall.
  *
- * @see Firewall
  * @author David Alves
+ * @see Firewall
  */
 public class FirewallOptions {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/ListOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/ListOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/ListOptions.java
index 81330ac..2f79f0f 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/ListOptions.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/ListOptions.java
@@ -16,15 +16,15 @@
  */
 package org.jclouds.googlecomputeengine.options;
 
-import org.jclouds.http.options.BaseHttpRequestOptions;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
 /**
  * Allows to optionally specify a filter, max results and a page token for <code>listFirstPage()</code> REST methods.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations/listFirstPage"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/operations/listFirstPage"/>
  */
 public class ListOptions extends BaseHttpRequestOptions {
 
@@ -65,7 +65,7 @@ public class ListOptions extends BaseHttpRequestOptions {
    }
 
    /**
-    * Sets Maximum count of results to be returned. Maximum and default value is 100. Acceptable values are 0 to
+    * Sets Maximum count of results to be returned. Maximum and default value is 100. Acceptable items are 0 to
     * 100, inclusive. (Default: 100)
     */
    public ListOptions maxResults(Integer maxResults) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/GlobalOperationDonePredicate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/GlobalOperationDonePredicate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/GlobalOperationDonePredicate.java
new file mode 100644
index 0000000..abd2b4c
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/GlobalOperationDonePredicate.java
@@ -0,0 +1,61 @@
+/*
+ * 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.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Operation;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+/**
+ * Tests that a Global Operation is done, returning the completed Operation when it is.
+ *
+ * @author David Alves
+ */
+public class GlobalOperationDonePredicate implements Predicate<AtomicReference<Operation>> {
+
+   private final GoogleComputeEngineApi api;
+   private final Supplier<String> project;
+
+   @Inject
+   GlobalOperationDonePredicate(GoogleComputeEngineApi api, @UserProject Supplier<String> project) {
+      this.api = api;
+      this.project = project;
+   }
+
+   @Override
+   public boolean apply(AtomicReference<Operation> input) {
+      checkNotNull(input, "input");
+      Operation current = api.getGlobalOperationApiForProject(project.get()).get(input.get().getName());
+      switch (current.getStatus()) {
+         case DONE:
+            input.set(current);
+            return true;
+         case PENDING:
+         case RUNNING:
+         default:
+            return false;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/OperationDonePredicate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/OperationDonePredicate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/OperationDonePredicate.java
deleted file mode 100644
index b58fe61..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/OperationDonePredicate.java
+++ /dev/null
@@ -1,60 +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.predicates;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.inject.Inject;
-import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
-import org.jclouds.googlecomputeengine.config.UserProject;
-import org.jclouds.googlecomputeengine.domain.Operation;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Tests that an Operation is done, returning the completed Operation when it is.
- *
- * @author David Alves
- */
-public class OperationDonePredicate implements Predicate<AtomicReference<Operation>> {
-
-   private final GoogleComputeEngineApi api;
-   private final Supplier<String> project;
-
-   @Inject
-   OperationDonePredicate(GoogleComputeEngineApi api, @UserProject Supplier<String> project) {
-      this.api = api;
-      this.project = project;
-   }
-
-   @Override
-   public boolean apply(AtomicReference<Operation> input) {
-      checkNotNull(input, "input");
-      Operation current = api.getOperationApiForProject(project.get()).get(input.get().getName());
-      switch (current.getStatus()) {
-         case DONE:
-            input.set(current);
-            return true;
-         case PENDING:
-         case RUNNING:
-         default:
-            return false;
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/ZoneOperationDonePredicate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/ZoneOperationDonePredicate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/ZoneOperationDonePredicate.java
new file mode 100644
index 0000000..7224785
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/ZoneOperationDonePredicate.java
@@ -0,0 +1,71 @@
+/*
+ * 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.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Operation;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+/**
+ * Tests that a Zone Operation is done, returning the completed Operation when it is.
+ *
+ * @author David Alves
+ */
+public class ZoneOperationDonePredicate implements Predicate<AtomicReference<Operation>> {
+
+   private final GoogleComputeEngineApi api;
+   private final Supplier<String> project;
+   private final Supplier<Map<URI, ? extends Location>> zones;
+
+   @Inject
+   ZoneOperationDonePredicate(GoogleComputeEngineApi api, @UserProject Supplier<String> project,
+                              @Memoized Supplier<Map<URI, ? extends Location>> zones) {
+      this.api = api;
+      this.project = project;
+      this.zones = zones;
+   }
+
+   @Override
+   public boolean apply(AtomicReference<Operation> input) {
+      checkNotNull(input, "input");
+      Operation current = api.getZoneOperationApiForProject(project.get())
+              .getInZone(zones.get().get(input.get().getZone().get()).getId(),
+                      input.get().getName());
+
+      switch (current.getStatus()) {
+         case DONE:
+            input.set(current);
+            return true;
+         case PENDING:
+         case RUNNING:
+         default:
+            return false;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadataTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadataTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadataTest.java
index 38a79e4..44994c0 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadataTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadataTest.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.googlecomputeengine;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
 import org.jclouds.View;
 import org.jclouds.apis.internal.BaseApiMetadataTest;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+
 /**
  * Tests that GoogleComputeApiMetadata is properly registered in ServiceLoader
  * <p/>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs/blob/1b30e222/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/PageSystemExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/PageSystemExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/PageSystemExpectTest.java
index a77b058..c9d9c70 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/PageSystemExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/PageSystemExpectTest.java
@@ -16,6 +16,9 @@
  */
 package org.jclouds.googlecomputeengine;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.testng.Assert.assertSame;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.Image;
@@ -26,9 +29,6 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
-import static org.testng.Assert.assertSame;
-
 /**
  * A test specifically for the paging system. The code used is common to all list() methods so we're using Images
  * but it could be anything else.
@@ -43,7 +43,7 @@ public class PageSystemExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images")
+                      ".com/compute/v1beta15/projects/myproject/global/images")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -66,7 +66,7 @@ public class PageSystemExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images?maxResults=3")
+                      ".com/compute/v1beta15/projects/myproject/global/images?maxResults=3")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -74,7 +74,7 @@ public class PageSystemExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images?pageToken" +
+                      ".com/compute/v1beta15/projects/myproject/global/images?pageToken" +
                       "=CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx&maxResults=3")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
@@ -83,7 +83,7 @@ public class PageSystemExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images?pageToken" +
+                      ".com/compute/v1beta15/projects/myproject/global/images?pageToken" +
                       "=CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2&maxResults=3")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();