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/20 02:39:34 UTC

[05/12] jclouds-labs-google git commit: Initial commit to add l7 loadbalancing features and tests to jclouds-labs-google

Initial commit to add l7 loadbalancing features and tests to jclouds-labs-google


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/commit/29f4013d
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/tree/29f4013d
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/diff/29f4013d

Branch: refs/heads/master
Commit: 29f4013dd27f6ec2b4d8296b7e0980ec79edb158
Parents: fbf8eb2
Author: ashmrtnz <as...@google.com>
Authored: Thu Aug 7 13:36:08 2014 -0700
Committer: Adrian Cole <ac...@twitter.com>
Committed: Wed Nov 19 17:37:47 2014 -0800

----------------------------------------------------------------------
 .../GoogleComputeEngineApi.java                 |   2 +
 .../ResourceViewEndpoint.java                   |  36 +
 .../GoogleComputeEngineHttpApiModule.java       |  13 +-
 .../domain/BackendService.java                  | 485 +++++++++++
 .../domain/BackendServiceGroupHealth.java       | 252 ++++++
 .../domain/ForwardingRule.java                  |   1 +
 .../googlecomputeengine/domain/Resource.java    | 292 +++++++
 .../domain/ResourceView.java                    | 267 ++++++
 .../domain/TargetHttpProxy.java                 | 132 +++
 .../googlecomputeengine/domain/UrlMap.java      | 825 +++++++++++++++++++
 .../domain/UrlMapValidateResult.java            | 345 ++++++++
 .../features/BackendServiceApi.java             | 267 ++++++
 .../features/ForwardingRuleApi.java             |   1 +
 .../features/ResourceViewApi.java               | 614 ++++++++++++++
 .../features/TargetHttpProxyApi.java            | 214 +++++
 .../googlecomputeengine/features/UrlMapApi.java | 267 ++++++
 .../BaseWithRegionAndNameToPagedIterable.java   |  83 ++
 .../BaseWithZoneAndNameToPagedIterable.java     |  83 ++
 .../internal/ParseBackendServices.java          |  63 ++
 .../ParseRegionResourceViewMembers.java         |  69 ++
 .../internal/ParseRegionResourceViews.java      |  67 ++
 .../internal/ParseTargetHttpProxies.java        |  63 ++
 .../functions/internal/ParseUrlMaps.java        |  63 ++
 .../internal/ParseZoneResourceViewMembers.java  |  70 ++
 .../internal/ParseZoneResourceViews.java        |  67 ++
 .../handlers/PayloadBinder.java                 |  56 ++
 .../options/BackendServiceOptions.java          | 216 +++++
 .../options/ForwardingRuleOptions.java          | 176 ++++
 .../options/ResourceOptions.java                |  69 ++
 .../options/ResourceViewOptions.java            | 149 ++++
 .../options/TargetHttpProxyOptions.java         | 103 +++
 .../options/UrlMapOptions.java                  | 214 +++++
 .../features/BackendServiceApiExpectTest.java   | 215 +++++
 .../features/BackendServiceApiLiveTest.java     | 152 ++++
 .../features/ForwardingRuleApiLiveTest.java     | 130 +++
 .../features/ResourceViewApiExpectTest.java     | 338 ++++++++
 .../features/ResourceViewApiLiveTest.java       | 190 +++++
 .../features/TargetHttpProxyApiExpectTest.java  | 168 ++++
 .../features/TargetHttpProxyApiLiveTest.java    | 126 +++
 .../features/UrlMapApiExpectTest.java           | 220 +++++
 .../features/UrlMapApiLiveTest.java             | 215 +++++
 .../BaseGoogleComputeEngineApiLiveTest.java     |  55 ++
 .../parse/ParseBackendServiceGetHealthTest.java |  51 ++
 .../parse/ParseBackendServiceListTest.java      |  65 ++
 .../parse/ParseBackendServiceTest.java          |  72 ++
 .../ParseGlobalForwardingRuleListTest.java      |  49 ++
 .../parse/ParseGlobalForwardingRuleTest.java    |  50 ++
 .../parse/ParseResourceViewListRegionTest.java  |  64 ++
 .../parse/ParseResourceViewListZoneTest.java    |  64 ++
 .../parse/ParseResourceViewRegionTest.java      |  50 ++
 .../ParseResourceViewResourceListTest.java      |  51 ++
 .../parse/ParseResourceViewZoneTest.java        |  50 ++
 .../parse/ParseTargetHttpProxyListTest.java     |  62 ++
 .../parse/ParseTargetHttpProxyTest.java         |  48 ++
 .../parse/ParseUrlMapListTest.java              |  61 ++
 .../parse/ParseUrlMapTest.java                  |  67 ++
 .../parse/ParseUrlMapValidateTest.java          |  51 ++
 .../src/test/resources/backend_service_get.json |  24 +
 .../resources/backend_service_get_health.json   |   9 +
 .../backend_service_get_health_request.json     |   1 +
 .../test/resources/backend_service_insert.json  |   9 +
 .../test/resources/backend_service_list.json    |  45 +
 .../resources/global_forwarding_rule_get.json   |  12 +
 .../global_forwarding_rule_insert.json          |   1 +
 .../resources/global_forwarding_rule_list.json  |  19 +
 .../global_forwarding_rule_setTarget.json       |   3 +
 .../resources/resource_view_get_region.json     |   9 +
 .../test/resources/resource_view_get_zone.json  |   9 +
 .../test/resources/resource_view_insert.json    |   1 +
 .../resources/resource_view_list_region.json    |  25 +
 .../test/resources/resource_view_list_zone.json |  25 +
 .../resources/resource_view_resources_list.json |   6 +
 .../test/resources/target_http_proxy_get.json   |   8 +
 .../resources/target_http_proxy_insert.json     |   1 +
 .../test/resources/target_http_proxy_list.json  |  24 +
 .../target_http_proxy_set_url_map.json          |   1 +
 .../src/test/resources/url_map_get.json         |  39 +
 .../src/test/resources/url_map_insert.json      |   1 +
 .../src/test/resources/url_map_list.json        |  56 ++
 .../src/test/resources/url_map_validate.json    |  17 +
 .../resources/url_map_validate_request.json     |   1 +
 .../googlecloud/internal/AdvancingIterator.java |   2 +
 82 files changed, 8635 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
index b8cc72f..95991c5 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
@@ -39,6 +39,8 @@ import org.jclouds.googlecomputeengine.features.RegionApi;
 import org.jclouds.googlecomputeengine.features.RouteApi;
 import org.jclouds.googlecomputeengine.features.SnapshotApi;
 import org.jclouds.googlecomputeengine.features.TargetPoolApi;
+import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi;
+import org.jclouds.googlecomputeengine.features.UrlMapApi;
 import org.jclouds.googlecomputeengine.features.ZoneApi;
 import org.jclouds.rest.annotations.Delegate;
 import org.jclouds.rest.annotations.Endpoint;

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/ResourceViewEndpoint.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/ResourceViewEndpoint.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/ResourceViewEndpoint.java
new file mode 100644
index 0000000..92b5ee6
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/ResourceViewEndpoint.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Interface designed to override the default endpoint for google-compute-engine
+ * so that ResourceViewApi calls go to the correct endpoint (URL).
+ *
+ * @see org.jclouds.googlecomputeengine.config.GoogleComputeEngineHttpAipModule#provideResourceViewUrl()
+ * for actual implementation.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@Qualifier
+public @interface ResourceViewEndpoint {}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/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 2a813d1..bb57d36 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
@@ -91,7 +91,6 @@ public final class GoogleComputeEngineHttpApiModule extends HttpApiModule<Google
             }
          }, defaultEndpoint), seconds, SECONDS);
       }
-
       // If the project name wasn't explicitly supplied, then we lookup via api.
       // This supplier must be defensive against any auth exception.
       return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier
@@ -140,4 +139,16 @@ public final class GoogleComputeEngineHttpApiModule extends HttpApiModule<Google
          return URI.create(defaultEndpoint.get() + "/projects/" + api.get(projectNumber).name());
       }
    }
+
+   @Provides
+   @Singleton
+   @ResourceViewEndpoint
+   public Supplier<URI> provideResourceViewUrl() {
+      return new Supplier<URI>() {
+         @Override
+         public URI get() {
+            return URI.create("https://www.googleapis.com/resourceviews/v1beta1");
+         }
+      };
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendService.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendService.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendService.java
new file mode 100644
index 0000000..67f11fd
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendService.java
@@ -0,0 +1,485 @@
+/*
+ * 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.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A backend service resource.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/backendServices"/>
+ * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/backend-service"/>
+ */
+public final class BackendService extends Resource {
+
+   private final Set<Backend> backends;
+   private final Set<URI> healthChecks;
+   private final Optional<Integer> timeoutSec;
+   private final Optional<Integer> port;
+   private final Optional<String> protocol;
+   private final Optional<String> fingerprint;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description",
+           "backends", "healthChecks", "timeoutSec", "port", "protocol",
+           "fingerprint"
+   })
+   private BackendService(String id, Date creationTimestamp, URI selfLink,
+                          String name, @Nullable String description,
+                          @Nullable Set<Backend> backends, Set<URI> healthChecks,
+                          @Nullable Integer timeoutSec, @Nullable Integer port,
+                          @Nullable String protocol,
+                          @Nullable String fingerprint) {
+      super(Kind.BACKEND_SERVICE, id, creationTimestamp, selfLink, name,
+            description);
+      this.healthChecks = checkNotNull(healthChecks);
+      this.backends = backends == null ? ImmutableSet.<Backend>of() : backends;
+      this.timeoutSec = fromNullable(timeoutSec);
+      this.port = fromNullable(port);
+      this.protocol = fromNullable(protocol);
+      this.fingerprint = fromNullable(fingerprint);
+   }
+
+   /**
+    * @return a list of backends this service uses.
+    */
+   public Set<Backend> getBackends() {
+      return backends;
+   }
+
+   /**
+    * @return a list of healthChecks this service uses.
+    */
+   public Set<URI> getHealthChecks() {
+      return healthChecks;
+   }
+
+   /**
+    * @return the time to wait for a backend before considering it a failed request.
+    */
+   public Optional<Integer> getTimeoutSec() {
+      return timeoutSec;
+   }
+
+   /**
+    * @return the port to connect to on the backend.
+    */
+   public Optional<Integer> getPort() {
+      return port;
+   }
+
+   /**
+    * @return the protocol.
+    */
+   public Optional<String> getProtocol() {
+      return protocol;
+   }
+
+   /**
+    * @return the fingerprint used for updating or patching this resource.
+    */
+   public Optional<String> getFingerprint() {
+      return fingerprint;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, name, backends, healthChecks, timeoutSec,
+                              port, protocol);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      BackendService that = BackendService.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.backends, that.backends)
+              && equal(this.healthChecks, that.healthChecks)
+              && equal(this.timeoutSec, that.timeoutSec)
+              && equal(this.port, that.port)
+              && equal(this.protocol, that.protocol);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("backends", backends)
+              .add("healthChecks", healthChecks)
+              .add("timeoutSec", timeoutSec.orNull())
+              .add("port", port.orNull())
+              .add("protocol", protocol.orNull())
+              .add("fingerprint", fingerprint.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromBackendService(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private ImmutableSet.Builder<Backend> backends = ImmutableSet.builder();
+      private ImmutableSet.Builder<URI> healthChecks = ImmutableSet.builder();
+      private Integer timeoutSec;
+      private Integer port;
+      private String protocol;
+      private String fingerprint;
+      
+      /**
+       * @see BackendService#getBackends()
+       */
+      public Builder backends(Set<Backend> backends) {
+         this.backends = ImmutableSet.<Backend>builder();
+         this.backends.addAll(backends);
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getBackends()
+       */
+      public Builder addBackend(Backend backend) {
+         this.backends.add(checkNotNull(backend, "backend"));
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getHealthChecks()
+       */
+      public Builder healthChecks(Set<URI> healthChecks) {
+         this.healthChecks = ImmutableSet.<URI>builder();
+         this.healthChecks.addAll(healthChecks);
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getHealthChecks()
+       */
+      public Builder addHealthCheck(URI healthCheck) {
+         this.healthChecks.add(checkNotNull(healthCheck, "healthCheck"));
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getTimeoutSec()
+       */
+      public Builder timeoutSec(Integer timeoutSec) {
+         this.timeoutSec = timeoutSec;
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getPort()
+       */
+      public Builder port(Integer port) {
+         this.port = port;
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getProtocol()
+       */
+      public Builder protocol(String protocol) {
+         this.protocol = protocol;
+         return this;
+      }
+      
+      /**
+       * @see BackendService#getFingerprint()
+       */
+      public Builder fingerprint(String fingerprint) {
+         this.fingerprint = fingerprint;
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public BackendService build() {
+         return new BackendService(super.id, super.creationTimestamp, super.selfLink, super.name,
+                                   super.description, backends.build(), healthChecks.build(),
+                                   timeoutSec, port, protocol, fingerprint);
+      }
+
+      public Builder fromBackendService(BackendService in) {
+         return super.fromResource(in)
+                 .backends(in.getBackends())
+                 .healthChecks(in.getHealthChecks())
+                 .timeoutSec(in.getTimeoutSec().orNull())
+                 .port(in.getPort().orNull())
+                 .protocol(in.getProtocol().orNull())
+                 .fingerprint(in.getFingerprint().orNull());
+      }
+
+   }
+   
+   public static final class Backend {
+      
+      private final Optional<String> description;
+      private final URI group;
+      private final Optional<String> balancingMode;
+      private final Optional<Float> maxUtilization;
+      private final Optional<Integer> maxRate;
+      private final Optional<Float> maxRatePerInstance;
+      private final Optional<Float> capacityScaler;
+      
+      @ConstructorProperties({
+              "description", "group", "balancingMode", "maxUtilization", "maxRate",
+              "maxRatePerInstance", "capacityScaler"
+      })
+      private Backend(@Nullable String description, URI group,
+                      @Nullable String balancingMode,
+                      @Nullable Float maxUtilization, @Nullable Integer maxRate,
+                      @Nullable Float maxRatePerInstance,
+                      @Nullable Float capacityScaler) {
+         this.description = fromNullable(description);
+         this.group = checkNotNull(group, "group");
+         this.balancingMode = fromNullable(balancingMode);
+         this.maxUtilization = fromNullable(maxUtilization);
+         this.maxRate = fromNullable(maxRate);
+         this.maxRatePerInstance = fromNullable(maxRatePerInstance);
+         this.capacityScaler = fromNullable(capacityScaler);
+      }
+
+      /**
+       * @return the description.
+       */
+      public Optional<String> getDescription() {
+         return description;
+      }
+
+      /**
+       * @return URI of the resource view this backend represents.
+       */
+      public URI getGroup() {
+         return group;
+      }
+
+      /**
+       * @return the balancingMode of this backend.
+       */
+      public Optional<String> getBalancingMode() {
+         return balancingMode;
+      }
+
+      /**
+       * @return the CPU utilization target for the group when the balancing
+       * mode is UTILIZATION.
+       */
+      public Optional<Float> getMaxUtilization() {
+         return maxUtilization;
+      }
+
+      /**
+       * @return the max RPS of the group.
+       */
+      public Optional<Integer> getMaxRate() {
+         return maxRate;
+      }
+
+      /**
+       * @return the max RPS per instance in the group.
+       */
+      public Optional<Float> getMaxRatePerInstance() {
+         return maxRatePerInstance;
+      }
+
+      /**
+       * @return the multiplier of the max capacity the group should serve up
+       * to.
+       */
+      public Optional<Float> getCapacityScaler() {
+         return capacityScaler;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(group, balancingMode, maxUtilization, maxRate,
+                                 maxRatePerInstance, capacityScaler);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         Backend that = Backend.class.cast(obj);
+         return equal(this.group, that.group)
+                 && equal(this.balancingMode, that.balancingMode)
+                 && equal(this.maxUtilization, that.maxUtilization)
+                 && equal(this.maxRate, that.maxRate)
+                 && equal(this.maxRatePerInstance, that.maxRatePerInstance)
+                 && equal(this.capacityScaler, that.capacityScaler);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this)
+               .omitNullValues()
+               .add("description", description.orNull())
+               .add("group", group)
+               .add("balancingMode", balancingMode.orNull())
+               .add("maxUtilization", maxUtilization.orNull())
+               .add("maxRate", maxRate.orNull())
+               .add("maxRatePerInstance", maxRatePerInstance.orNull())
+               .add("capacityScaler", capacityScaler.orNull());
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromBackendServicesBackend(this);
+      }
+
+      public static final class Builder {
+         
+         String description;
+         URI group;
+         String balancingMode;
+         Float maxUtilization;
+         Integer maxRate;
+         Float maxRatePerInstance;
+         Float capacityScaler;
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getDescription()
+          */
+         public Builder description(String description) {
+            this.description = description;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getGroup()
+          */
+         public Builder group(URI group) {
+            this.group = group;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getBalancingMode()
+          */
+         public Builder balancingMode(String balancingMode) {
+            this.balancingMode = balancingMode;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getMaxUtilization()
+          */
+         public Builder maxUtilization(Float maxUtilization) {
+            this.maxUtilization = maxUtilization;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getMaxRate()
+          */
+         public Builder maxRate(Integer maxRate) {
+            this.maxRate = maxRate;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getMaxRatePerInstance()
+          */
+         public Builder maxRatePerInstance(Float maxRatePerInstance) {
+            this.maxRatePerInstance = maxRatePerInstance;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendService.Backend#getCapacityScaler()
+          */
+         public Builder capacityScaler(Float capacityScaler) {
+            this.capacityScaler = capacityScaler;
+            return this;
+         }
+         
+         public Backend build() {
+            return new Backend(description, group, balancingMode,
+                               maxUtilization, maxRate, maxRatePerInstance,
+                               capacityScaler);
+         }
+         
+         public Builder fromBackendServicesBackend(Backend in) {
+            return new Builder().description(in.getDescription().orNull())
+                                .group(in.getGroup())
+                                .balancingMode(in.getBalancingMode().orNull())
+                                .maxUtilization(in.getMaxUtilization().orNull())
+                                .maxRate(in.getMaxRate().orNull())
+                                .maxRatePerInstance(in.getMaxRatePerInstance().orNull())
+                                .capacityScaler(in.getCapacityScaler().orNull());
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendServiceGroupHealth.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendServiceGroupHealth.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendServiceGroupHealth.java
new file mode 100644
index 0000000..bdb2db2
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/BackendServiceGroupHealth.java
@@ -0,0 +1,252 @@
+/*
+ * 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.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Set;
+
+import org.jclouds.googlecomputeengine.domain.Resource.Kind;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents the health of a backend service group.
+ * 
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/backendServices/getHealth"/>
+ */
+public class BackendServiceGroupHealth {
+   
+   protected final Kind kind;
+   protected final Set<HealthStatus> healthStatuses;
+   
+   @ConstructorProperties({
+           "healthStatus"
+   })
+   private BackendServiceGroupHealth(Set<HealthStatus> healthStatuses) {
+      this.kind = Kind.BACKEND_SERVICE_GROUP_HEALTH;
+      this.healthStatuses = healthStatuses == null ? ImmutableSet.<HealthStatus>of() : healthStatuses;
+   }
+   
+   /**
+    * @return the Type of the resource.
+    */
+   public Kind getKind() {
+      return kind;
+   }
+   
+   /**
+    * @return a Set of HealthStatus objects denoting the health of instances. 
+    */
+   public Set<HealthStatus> getHealthStatuses() {
+      return healthStatuses;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, healthStatuses);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      BackendServiceGroupHealth that = BackendServiceGroupHealth.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.healthStatuses, that.healthStatuses);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public Objects.ToStringHelper string() {
+      return toStringHelper(this).omitNullValues()
+                                 .add("healthStatuses", healthStatuses);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+   
+   public static Builder builder() {
+      return new Builder();
+   }
+   
+   public static final class Builder {
+      
+      ImmutableSet.Builder<HealthStatus> healthStatuses = ImmutableSet.builder();
+      
+      /**
+       * @see BackendServiceGroupHealth#getHealthStatus()
+       */
+      public Builder addHealthStatus(HealthStatus healthStatus) {
+         this.healthStatuses.add(checkNotNull(healthStatus, "healthStatus"));
+         return this;
+      }
+      
+      /**
+       * @see BackendServiceGroupHealth#getHealthStatus()
+       */
+      public Builder healthStatuses(Set<HealthStatus> healthStatuses) {
+         this.healthStatuses = ImmutableSet.builder();
+         this.healthStatuses.addAll(healthStatuses);
+         return this;
+      }
+      
+      public BackendServiceGroupHealth build() {
+         return new BackendServiceGroupHealth(healthStatuses.build());
+      }
+   }
+   
+   /**
+    * Represents the health status of a particular instance.
+    *
+    */
+   public static final class HealthStatus {
+      
+      private Optional<String> ipAddress;
+      private URI instance;
+      private String healthState;
+      
+      @ConstructorProperties({
+              "ipAddress", "instance", "healthState"
+      })
+      private HealthStatus(@Nullable String ipAddress, URI instance,
+                           String healthState) {
+         this.ipAddress = fromNullable(ipAddress);
+         this.instance = instance;
+         this.healthState = healthState;
+      }
+
+      /**
+       * @return the IP address of the instance.
+       */
+      public Optional<String> getIpAddress() {
+         return ipAddress;
+      }
+
+      /**
+       * @return the URL of the instance.
+       */
+      public URI getInstance() {
+         return instance;
+      }
+
+      /**
+       * @return the health state of the instance.
+       */
+      public String getHealthState() {
+         return healthState;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(ipAddress, instance, healthState);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         HealthStatus that = HealthStatus.class.cast(obj);
+         return equal(this.ipAddress, that.ipAddress)
+                 && equal(this.instance, that.instance)
+                 && equal(this.healthState, that.healthState);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this).omitNullValues()
+                                    .add("ipAddress", ipAddress.orNull())
+                                    .add("instance", instance)
+                                    .add("healthState", healthState);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+      
+      public static Builder builder() {
+         return new Builder();
+      }
+      
+      public static final class Builder {
+         
+         private String healthState;
+         private String ipAddress;
+         private URI instance;
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendServiceGroupHealth.HealthStatus#getHealthState()
+          */
+         public Builder healthState(String healthState) {
+            this.healthState = healthState;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendServiceGroupHealth.HealthStatus#getIpAddress()
+          */
+         public Builder ipAddress(String ipAddress) {
+            this.ipAddress = ipAddress;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.BackendServiceGroupHealth.HealthStatus#getInstance()
+          */
+         public Builder instance(URI instance) {
+            this.instance = instance;
+            return this;
+         }
+         
+         public HealthStatus build() {
+            return new HealthStatus(ipAddress, instance, healthState);
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ForwardingRule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ForwardingRule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ForwardingRule.java
index 7216da9..4b4abb7 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ForwardingRule.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ForwardingRule.java
@@ -80,4 +80,5 @@ public abstract class ForwardingRule {
 
    ForwardingRule() {
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Resource.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Resource.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Resource.java
new file mode 100644
index 0000000..6584522
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Resource.java
@@ -0,0 +1,292 @@
+/*
+ * 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.MoreObjects.ToStringHelper;
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+/**
+ * Base class for Google Compute Engine resources.
+ */
+@Beta
+public class Resource {
+
+   public enum Kind {
+      ADDRESS,
+      ADDRESS_LIST,
+      BACKEND_SERVICE,
+      BACKEND_SERVICE_LIST,
+      BACKEND_SERVICE_GROUP_HEALTH,
+      DISK,
+      DISK_LIST,
+      FIREWALL,
+      FIREWALL_LIST,
+      FORWARDING_RULE,
+      FORWARDING_RULE_LIST,
+      IMAGE,
+      IMAGE_LIST,
+      OPERATION,
+      OPERATION_LIST,
+      INSTANCE,
+      INSTANCE_LIST,
+      MACHINE_TYPE,
+      MACHINE_TYPE_LIST,
+      PROJECT,
+      NETWORK,
+      NETWORK_LIST,
+      REGION,
+      REGION_LIST,
+      RESOURCE_VIEW,
+      RESOURCE_VIEW_LIST,
+      RESOURCE_VIEW_MEMBER_LIST,
+      ROUTE,
+      ROUTE_LIST,
+      SNAPSHOT,
+      SNAPSHOT_LIST,
+      TARGET_HTTP_PROXY,
+      TARGET_HTTP_PROXY_LIST,
+      URL_MAP,
+      URL_MAP_LIST,
+      ZONE,
+      ZONE_LIST;
+
+      public String value() {
+         return Joiner.on("#").join("compute", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()));
+      }
+
+      @Override
+      public String toString() {
+         return value();
+      }
+
+      public static Kind fromValue(String kind) {
+         return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat
+                 .UPPER_UNDERSCORE,
+                 Iterables.getLast(Splitter.on("#").split(checkNotNull(kind,
+                         "kind")))));
+      }
+   }
+
+   protected final Kind kind;
+   protected final String id;
+   protected final Optional<Date> creationTimestamp;
+   protected final URI selfLink;
+   protected final String name;
+   protected final Optional<String> description;
+
+   @ConstructorProperties({
+           "kind", "id", "creationTimestamp", "selfLink", "name", "description"
+   })
+   protected Resource(Kind kind, String id, Date creationTimestamp, URI selfLink, String name,
+                      String description) {
+      this.kind = checkNotNull(kind, "kind");
+      this.id = checkNotNull(id, "id");
+      this.creationTimestamp = fromNullable(creationTimestamp);
+      this.selfLink = checkNotNull(selfLink, "selfLink");
+      this.name = checkNotNull(name, "name");
+      this.description = fromNullable(description);
+   }
+
+   /**
+    * @return the Type of the resource
+    */
+   public Kind getKind() {
+      return kind;
+   }
+
+   /**
+    * @return unique identifier for the resource; defined by the server.
+    */
+   public String getId() {
+      return id;
+   }
+
+   /**
+    * @return creation timestamp in RFC3339 text format.
+    */
+   public Optional<Date> getCreationTimestamp() {
+      return creationTimestamp;
+   }
+
+   /**
+    * @return server defined URL for the resource.
+    */
+   public URI getSelfLink() {
+      return selfLink;
+   }
+
+   /**
+    * @return name of the resource.
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * @return an optional textual description of the resource.
+    */
+   @Nullable
+   public Optional<String> getDescription() {
+      return description;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Resource that = Resource.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name);
+   }
+
+   protected ToStringHelper string() {
+      return toStringHelper(this)
+              .omitNullValues()
+              .add("kind", kind)
+              .add("id", id)
+              .add("name", name)
+              .add("creationTimestamp", creationTimestamp.orNull())
+              .add("selfLink", selfLink)
+              .add("name", name)
+              .add("description", description.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromResource(this);
+   }
+
+   public abstract static class Builder<T extends Builder<T>> {
+
+      protected abstract T self();
+
+      protected Kind kind;
+      protected String id;
+      protected Date creationTimestamp;
+      protected URI selfLink;
+      protected String name;
+      protected String description;
+
+      /**
+       * @see Resource#getKind()
+       */
+      protected T kind(Kind kind) {
+         this.kind = kind;
+         return self();
+      }
+
+      /**
+       * @see Resource#getId()
+       */
+      public T id(String id) {
+         this.id = id;
+         return self();
+      }
+
+      /**
+       * @see Resource#getCreationTimestamp()
+       */
+      public T creationTimestamp(Date creationTimestamp) {
+         this.creationTimestamp = creationTimestamp;
+         return self();
+      }
+
+      /**
+       * @see Resource#getSelfLink()
+       */
+      public T selfLink(URI selfLink) {
+         this.selfLink = selfLink;
+         return self();
+      }
+
+      /**
+       * @see Resource#getName()
+       */
+      public T name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      /**
+       * @see Resource#getDescription()
+       */
+      public T description(String description) {
+         this.description = description;
+         return self();
+      }
+
+      public Resource build() {
+         return new Resource(kind, id, creationTimestamp, selfLink, name, description);
+      }
+
+      public T fromResource(Resource in) {
+         return this
+                 .kind(in.getKind())
+                 .id(in.getId())
+                 .creationTimestamp(in.getCreationTimestamp().orNull())
+                 .selfLink(in.getSelfLink())
+                 .name(in.getName())
+                 .description(in.getDescription().orNull());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ResourceView.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ResourceView.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ResourceView.java
new file mode 100644
index 0000000..36d831f
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ResourceView.java
@@ -0,0 +1,267 @@
+/*
+ * 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.Objects.equal;
+import static com.google.common.base.Optional.absent;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a resource view resource.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+ * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map"/>
+ */
+@Beta
+public final class ResourceView extends Resource {
+
+   private final Optional<Integer> numMembers;
+   private final Set<URI> members;
+   private final Optional<Date> lastModified;
+   private final Map<String, String> labels;
+   private final Optional<String> region;
+   private final Optional<String> zone;
+
+   @ConstructorProperties({
+           "id", "creationTime", "selfLink", "name", "description", "numMembers", "members",
+           "lastModified", "labels"
+   })
+   protected ResourceView(String id, Date creationTimestamp, URI selfLink, String name,
+                          @Nullable String description, @Nullable Integer numMembers,
+                          @Nullable Set<URI> members, @Nullable Date lastModified,
+                          @Nullable Map<String, String> labels) {
+      // TODO: (ashmrtnz) remove the '-1' that is passed as the id. Currently
+      // resource views do not return an id and Resource requires one.
+      super(Kind.RESOURCE_VIEW, "-1", creationTimestamp, selfLink, name, description);
+      this.numMembers = fromNullable(numMembers);
+      this.members = members == null ? ImmutableSet.<URI>of() : members;
+      this.lastModified = fromNullable(lastModified);
+      this.labels = labels == null ? ImmutableMap.<String, String>of() : labels;
+      
+      // This is not ideal, but it is the only way I can get region or zone.
+      // TODO: change this when it is no longer beta because it is based on the
+      // form of the self link
+      String[] parts = this.selfLink.toString().split("/+");
+      if (!parts[3].equals("v1beta1")) {
+    	  throw new RuntimeException("Expected version v1beta1 but got version" + parts[3]);
+      }
+      if (parts[6].equals("zones")) {
+         this.zone = Optional.<String>of(parts[7]);
+         this.region = absent();
+      } else if (parts[6].equals("regions")) {
+         this.zone = absent();
+         this.region = Optional.<String>of(parts[7]);
+      } else {
+    	  throw new RuntimeException("Could not find zone or region");
+      }
+         
+   }
+   
+   /**
+    * @return the number of resources in this resource view.
+    */
+   public Optional<Integer> getNumMembers() {
+      return numMembers;
+   }
+
+   
+   /**
+    * @return a Set of URIs of the resources in this resource view.
+    */
+   public Set<URI> getMembers() {
+      return members;
+   }
+
+   
+   /**
+    * @return the date this resource view was last modified.
+    */
+   public Optional<Date> getLastModified() {
+      return lastModified;
+   }
+
+   
+   /**
+    * @return the labels for this resource view.
+    */
+   public Map<String, String> getLabels() {
+      return labels;
+   }
+   
+   /**
+    * @return the region of this resource view.
+    */
+   public Optional<String> getRegion() {
+      return region;
+   }
+   
+   /**
+    * @return the zone of this resource view.
+    */
+   public Optional<String> getZone() {
+      return zone;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, name, numMembers, members, lastModified,
+                              labels, zone, region);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      ResourceView that = ResourceView.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.numMembers, that.numMembers)
+              && equal(this.members, that.members)
+              && equal(this.lastModified, that.lastModified)
+              && equal(this.labels, that.labels)
+              && equal(this.zone, that.zone)
+              && equal(this.region, that.region);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("numMembers", numMembers.orNull())
+              .add("memebers", members)
+              .add("lastModified", lastModified.orNull())
+              .add("labels", labels)
+              .add("region", region.orNull())
+              .add("zone", zone.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromResourceView(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private Integer numMembers;
+      private ImmutableSet.Builder<URI> members = ImmutableSet.<URI>builder();
+      private Date lastModified;
+      private ImmutableMap.Builder<String, String> labels = ImmutableMap.<String, String>builder();
+
+      /**
+       * @see ResourceView#getNumMembers()
+       */
+      public Builder numMembers(Integer numMembers) {
+         this.numMembers = numMembers;
+         return this;
+      }
+      
+      /**
+       * @see ResourceView#getMembers()
+       */
+      public Builder addMember(URI member) {
+         this.members.add(checkNotNull(member));
+         return this;
+      }
+
+      /**
+       * @see ResourceView#getMembers()
+       */
+      public Builder members(Set<URI> members) {
+         this.members = ImmutableSet.<URI>builder();
+         this.members.addAll(members);
+         return this;
+      }
+      
+      /**
+       * @see ResourceView#getLastModified()
+       */
+      public Builder lastModified(Date lastModified) {
+         this.lastModified = lastModified;
+         return this;
+      }
+      
+      /**
+       * @see ResourceView#getLabels()
+       */
+      public Builder addLabel(String key, String value) {
+         labels.put(checkNotNull(key), checkNotNull(value));
+         return this;
+      }
+      
+      /**
+       * @see ResourceView#getLabels()
+       */
+      public Builder labels(Map<String, String> labels) {
+         this.labels = ImmutableMap.<String, String>builder();
+         this.labels.putAll(labels);
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public ResourceView build() {
+         return new ResourceView(super.id, super.creationTimestamp,
+                                 super.selfLink, super.name, super.description,
+                                 numMembers, members.build(), lastModified,
+                                 labels.build());
+      }
+
+      public Builder fromResourceView(ResourceView in) {
+         return super.fromResource(in).numMembers(in.getNumMembers().orNull())
+                 .members(in.getMembers())
+                 .lastModified(in.getLastModified().orNull())
+                 .labels(in.getLabels());
+      }
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/TargetHttpProxy.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/TargetHttpProxy.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/TargetHttpProxy.java
new file mode 100644
index 0000000..fe4acc3
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/TargetHttpProxy.java
@@ -0,0 +1,132 @@
+/*
+ * 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.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+/**
+ * A target http proxy resource.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/targetHttpProxies"/>
+ * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/target-http-proxy"/>
+ */
+@Beta
+public final class TargetHttpProxy extends Resource {
+
+   private final URI urlMap;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "urlMap",
+   })
+   private TargetHttpProxy(String id, Date creationTimestamp, URI selfLink, String name,
+                           @Nullable String description, URI urlMap) {
+      super(Kind.TARGET_HTTP_PROXY, id, creationTimestamp, selfLink, name, description);
+      this.urlMap = checkNotNull(urlMap, "urlMap");
+   }
+
+   /**
+    * @return the url map this proxy points to.
+    */
+   public URI getUrlMap() {
+      return urlMap;
+   }
+   
+   /**
+    *  {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, name, urlMap);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      TargetHttpProxy that = TargetHttpProxy.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.urlMap, that.urlMap);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("urlMap", urlMap);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromTargetHttpProxy(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private URI urlMap;
+      
+      /**
+       * @see TargetHttpProxy#getUrlMap()
+       */
+      public Builder urlMap(URI urlMap) {
+         this.urlMap = urlMap;
+         return this;
+      }
+      
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public TargetHttpProxy build() {
+         return new TargetHttpProxy(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, urlMap);
+      }
+
+      public Builder fromTargetHttpProxy(TargetHttpProxy in) {
+         return super.fromResource(in)
+                 .urlMap(in.getUrlMap());
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/29f4013d/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/UrlMap.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/UrlMap.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/UrlMap.java
new file mode 100644
index 0000000..ec2ecd7
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/UrlMap.java
@@ -0,0 +1,825 @@
+/*
+ * 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.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a url map resource.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+ * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map"/>
+ */
+@Beta
+public final class UrlMap extends Resource {
+
+   private final Set<HostRule> hostRules;
+   private final Set<PathMatcher> pathMatchers;
+   private final Set<UrlMapTest> urlMapTests;
+   private final URI defaultService;
+   private final Optional<String> fingerprint;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "hostRules","pathMatchers",
+           "tests", "defaultService", "fingerprint"
+   })
+   protected UrlMap(String id, Date creationTimestamp, URI selfLink, String name,
+                    @Nullable String description, @Nullable Set<HostRule> hostRules,
+                    @Nullable Set<PathMatcher> pathMatchers,
+                    @Nullable Set<UrlMapTest> urlMapTests, URI defaultService,
+                    @Nullable String fingerprint) {
+      super(Kind.URL_MAP, id, creationTimestamp, selfLink, name, description);
+      this.defaultService = checkNotNull(defaultService, "default service");
+      this.pathMatchers = pathMatchers == null ? ImmutableSet.<PathMatcher>of() : pathMatchers;
+      this.urlMapTests = urlMapTests == null ? ImmutableSet.<UrlMapTest>of() : urlMapTests;
+      this.hostRules = hostRules == null ? ImmutableSet.<HostRule>of() : hostRules;
+      this.fingerprint = fromNullable(fingerprint);
+   }
+
+   /**
+    * @return the hostRules for this urlMap.
+    */
+   public Set<HostRule> getHostRules() {
+      return hostRules;
+   }
+
+   /**
+    * @return the pathMatchers for this urlMap.
+    */
+   public Set<PathMatcher> getPathMatchers() {
+      return pathMatchers;
+   }
+
+   /**
+    * @return the tests for this urlMap.
+    */
+   public Set<UrlMapTest> getTests() {
+      return urlMapTests;
+   }
+
+   /**
+    * @return the defaultService for this urlMap.
+    */
+   public URI getDefaultService() {
+      return defaultService;
+   }
+
+   /**
+    * @return the fingerprint for this urlMap.
+    */
+   public Optional<String> getFingerprint() {
+      return fingerprint;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name, kind, hostRules, pathMatchers, urlMapTests,
+                              defaultService);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      UrlMap that = UrlMap.class.cast(obj);
+      return equal(this.name, that.name)
+              && equal(this.kind, that.kind)
+              && equal(this.hostRules, that.hostRules)
+              && equal(this.pathMatchers, that.pathMatchers)
+              && equal(this.urlMapTests, that.urlMapTests)
+              && equal(this.defaultService, that.defaultService);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("hostRules", hostRules)
+              .add("pathMatchers", pathMatchers)
+              .add("tests", urlMapTests)
+              .add("defaultService", defaultService)
+              .add("fingerprint", fingerprint.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromUrlMap(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private ImmutableSet.Builder<HostRule> hostRules = ImmutableSet.builder();
+      private ImmutableSet.Builder<PathMatcher> pathMatchers = ImmutableSet.builder();
+      private ImmutableSet.Builder<UrlMapTest> urlMapTests = ImmutableSet.builder();
+      private URI defaultService;
+      private String fingerprint;
+
+      /**
+       * @see UrlMap#getHostRules()
+       */
+      public Builder addHostRule(HostRule hostRule) {
+         this.hostRules.add(checkNotNull(hostRule, "hostRule"));
+         return this;
+      }
+
+      /**
+       * @see UrlMap#getHostRules()
+       */
+      public Builder hostRules(Set<HostRule> hostRules) {
+         this.hostRules = ImmutableSet.builder();
+         this.hostRules.addAll(hostRules);
+         return this;
+      }
+      
+      /**
+       * @see UrlMap#getPathMatchers()
+       */
+      public Builder addPathMatcher(PathMatcher pathMatcher) {
+         this.pathMatchers.add(checkNotNull(pathMatcher, "pathMatcher"));
+         return this;
+      }
+
+      /**
+       * @see UrlMap#getPathMatchers()
+       */
+      public Builder pathMatchers(Set<PathMatcher> pathMatchers) {
+         this.pathMatchers = ImmutableSet.builder();
+         this.pathMatchers.addAll(pathMatchers);
+         return this;
+      }
+      
+      /**
+       * @see UrlMap#getTests()
+       */
+      public Builder addUrlMapTest(UrlMapTest urlMapTest) {
+         this.urlMapTests.add(checkNotNull(urlMapTest, "test"));
+         return this;
+      }
+
+      /**
+       * @see UrlMap#getTests()
+       */
+      public Builder urlMapTests(Set<UrlMapTest> urlMapTests) {
+         this.urlMapTests = ImmutableSet.builder();
+         this.urlMapTests.addAll(urlMapTests);
+         return this;
+      }
+      
+      /**
+       * @see UrlMap#getDefaultService()
+       */
+      public Builder defaultService(URI defaultService) {
+         this.defaultService = defaultService;
+         return this;
+      }
+      
+      /**
+       * @see UrlMap#getFingerprint()
+       */
+      public Builder fingerprint(String fingerprint) {
+         this.fingerprint = fingerprint;
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public UrlMap build() {
+         return new UrlMap(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, hostRules.build(), pathMatchers.build(), urlMapTests.build(),
+                 defaultService, fingerprint);
+      }
+
+      public Builder fromUrlMap(UrlMap in) {
+         return super.fromResource(in).hostRules(in.getHostRules()).pathMatchers(in.getPathMatchers())
+                  .urlMapTests(in .getTests()).defaultService(in.getDefaultService())
+                  .fingerprint(in.getFingerprint().orNull());
+      }
+
+   }
+
+   /**
+    * An urlMap hostRule used to filter requests based on hostname. Controls what traffic is sent to
+    * which path matcher.
+    *
+    * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+    * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map#adding_host_rules"/>
+    */
+   public static final class HostRule {
+
+      private final Optional<String> description;
+      private final Set<String> hosts;
+      private final String pathMatcher;
+      
+      @ConstructorProperties({
+              "description", "hosts", "pathMatcher"
+      })
+      private HostRule(@Nullable String description, @Nullable Set<String> hosts,
+                       @Nullable String pathMatcher) {
+         this.pathMatcher = checkNotNull(pathMatcher, "pathMatcher");
+         this.hosts = hosts == null ? ImmutableSet.<String>of() : hosts;
+         this.description = fromNullable(description);
+      }
+
+      /**
+       * @return the description.
+       */
+      public Optional<String> getDescription() {
+         return description;
+      }
+
+      /**
+       * @return the hosts.
+       */
+      public Set<String> getHosts() {
+         return hosts;
+      }
+
+      /**
+       * @return the pathMatcher this hostRule uses.
+       */
+      public String getPathMatcher() {
+         return pathMatcher;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(hosts, pathMatcher);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         HostRule that = HostRule.class.cast(obj);
+         return equal(this.hosts, that.hosts)
+                 && equal(this.pathMatcher, that.pathMatcher);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .omitNullValues()
+                 .add("hosts", hosts)
+                 .add("pathMatcher", pathMatcher);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromHostRule(this);
+      }
+
+      public static final class Builder {
+
+         private String description;
+         private ImmutableSet.Builder<String> hosts = ImmutableSet.<String>builder();
+         private String pathMatcher;
+
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.HostRule#getDescription()
+          */
+         public Builder description(String description) {
+            this.description = description;
+            return this;
+         }
+
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.HostRule#getHosts()
+          */
+         public Builder addHost(String host) {
+            this.hosts.add(checkNotNull(host, "host"));
+            return this;
+         }
+
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.HostRule#getHosts()
+          */
+         public Builder hosts(Set<String> hosts) {
+            this.hosts = ImmutableSet.builder();
+            this.hosts.addAll(hosts);
+            return this;
+         }
+
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.HostRule#getPathMatcher()
+          */
+         public Builder pathMatcher(String pathMatcher) {
+            this.pathMatcher = pathMatcher;
+            return this;
+         }
+
+         public HostRule build() {
+            return new HostRule(description, hosts.build(), pathMatcher);
+         }
+
+         public Builder fromHostRule(HostRule hostRule) {
+            return new Builder().description(hostRule.getDescription().orNull())
+                                .hosts(hostRule.getHosts())
+                                .pathMatcher(hostRule.getPathMatcher());
+         }
+      }
+
+   }
+   
+   /**
+    * An urlMap PathMatcher used to route requests based on the url given.
+    *
+    * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+    * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map#adding_path_matchers"/>
+    */
+   public static final class PathMatcher {
+      
+      private final String name;
+      private final Optional<String> description;
+      private final URI defaultService;
+      private final Set<PathRule> pathRules;
+      
+      @ConstructorProperties({
+              "name", "description", "defaultService", "pathRules"
+      })
+      private PathMatcher(String name, @Nullable String description,
+                          URI defaultService, @Nullable Set<PathRule> pathRules) {
+         this.name = checkNotNull(name, "name");
+         this.description = fromNullable(description);
+         this.defaultService = checkNotNull(defaultService, "defaultService");
+         this.pathRules = pathRules == null ? ImmutableSet.<PathRule>of() : pathRules;
+      }
+
+      /**
+       * @return the name.
+       */
+      public String getName() {
+         return name;
+      }
+
+      /**
+       * @return the description.
+       */
+      public Optional<String> getDescription() {
+         return description;
+      }
+
+      /**
+       * @return the defaultService this PathMatcher will send unmatched traffic to.
+       */
+      public URI getDefaultService() {
+         return defaultService;
+      }
+
+      /**
+       * @return the pathRules this PathMatcher compares requests against.
+       */
+      public Set<PathRule> getPathRules() {
+         return pathRules;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(name, defaultService, pathRules);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         PathMatcher that = PathMatcher.class.cast(obj);
+         return equal(this.name, that.name)
+                 && equal(this.defaultService, that.defaultService)
+                 && equal(this.pathRules, that.pathRules);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .omitNullValues()
+                 .add("name", name)
+                 .add("defaultService", defaultService)
+                 .add("pathRules", pathRules);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromPathMatcher(this);
+      }
+
+      public static final class Builder {
+         
+         private String name;
+         private String description;
+         private URI defaultService;
+         private ImmutableSet.Builder<PathRule> pathRules = ImmutableSet.<PathRule>builder();
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathMatcher#getName()
+          */
+         public Builder name(String name) {
+            this.name = name;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathMatcher#getDescription()
+          */
+         public Builder description(String description) {
+            this.description = description;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathMatcher#getDefaultService()
+          */
+         public Builder defaultService(URI defaultService) {
+            this.defaultService = defaultService;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathMatcher#getPathRules()
+          */
+         public Builder addPathRule(PathRule pathRule) {
+            this.pathRules.add(checkNotNull(pathRule, "pathRule"));
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathMatcher#getPathRules()
+          */
+         public Builder pathRules(Set<PathRule> pathRules) {
+            this.pathRules = ImmutableSet.builder();
+            this.pathRules.addAll(pathRules);
+            return this;
+         }
+         
+         public PathMatcher build() {
+            return new PathMatcher(name, description, defaultService, pathRules.build());
+         }
+         
+         public Builder fromPathMatcher(PathMatcher pathMatcher) {
+            return new Builder().name(pathMatcher.getName())
+                                .description(pathMatcher.getDescription().orNull())
+                                .defaultService(pathMatcher.getDefaultService())
+                                .pathRules(pathMatcher.getPathRules());
+         }
+      }
+      
+   }
+   
+   /**
+    * An urlMap PathRule used to route requests based on the url given.
+    *
+    * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+    * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map#adding_path_matchers"/>
+    */
+   public static final class PathRule {
+      
+      private final Set<String> paths;
+      private final URI service;
+      
+      @ConstructorProperties({
+              "paths", "service"
+      })
+      private PathRule(Set<String> paths, URI service) {
+         this.paths = checkNotNull(paths, "paths");
+         this.service = checkNotNull(service, "service");
+      }
+
+      /**
+       * @return the paths this PathRule compares requests against.
+       */
+      public Set<String> getPaths() {
+         return paths;
+      }
+
+      /**
+       * @return the service requests will be routed to if they match a path.
+       */
+      public URI getService() {
+         return service;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(paths, service);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         PathRule that = PathRule.class.cast(obj);
+         return equal(this.paths, that.paths)
+                 && equal(this.service, that.service);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .omitNullValues()
+                 .add("paths", paths)
+                 .add("service", service);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromPathRule(this);
+      }
+
+      public static final class Builder {
+         
+         private ImmutableSet.Builder<String> paths = ImmutableSet.<String>builder();
+         private URI service;
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathRule#getPaths()
+          */
+         public Builder addPath(String path) {
+            this.paths.add(checkNotNull(path, "path"));
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathRule#getPaths()
+          */
+         public Builder paths(Set<String> paths) {
+            this.paths = ImmutableSet.builder();
+            this.paths.addAll(paths);
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.PathRule#getService()
+          */
+         public Builder service(URI service) {
+            this.service = service;
+            return this;
+         }
+         
+         public PathRule build() {
+            return new PathRule(paths.build(), service);
+         }
+         
+         public Builder fromPathRule(PathRule pathRule) {
+            return new Builder().paths(pathRule.getPaths()).service(pathRule.getService());
+         }
+      }
+   }
+   
+   /**
+    * An urlMap Test which validates that host rules and path rules behave as they should.
+    *
+    * @see <a href="https://developers.google.com/compute/docs/reference/latest/urlMaps"/>
+    * @see <a href="https://developers.google.com/compute/docs/load-balancing/http/url-map#testing_url_maps"/>
+    */
+   public static final class UrlMapTest {
+      
+      private final Optional<String> description;
+      private final String host;
+      private final String path;
+      private final URI service;
+      
+      @ConstructorProperties({
+              "description", "host", "path", "service"
+      })
+      private UrlMapTest(@Nullable String description, String host, String path, URI service) {
+         this.description = fromNullable(description);
+         this.host = checkNotNull(host, "host");
+         this.path = checkNotNull(path, "path");
+         this.service = checkNotNull(service, "service");
+      }
+
+      /**
+       * @return description of this test.
+       */
+      public Optional<String> getDescription() {
+         return description;
+      }
+
+      /**
+       * @return the host used in the test request.
+       */
+      public String getHost() {
+         return host;
+      }
+
+      /**
+       * @return the path used in the test request.
+       */
+      public String getPath() {
+         return path;
+      }
+
+      /**
+       * @return the service that the request should map to.
+       */
+      public URI getService() {
+         return service;
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(host, path, service);
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         UrlMapTest that = UrlMapTest.class.cast(obj);
+         return equal(this.host, that.host)
+                 && equal(this.path, that.path)
+                 && equal(this.service, that.service);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .omitNullValues()
+                 .add("description", description.orNull())
+                 .add("host", host)
+                 .add("path", path)
+                 .add("service", service);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+      
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromTest(this);
+      }
+
+      public static final class Builder {
+         
+         private String description;
+         private String host;
+         private String path;
+         private URI service;
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.UrlMapTest#getDesciption()
+          */
+         public Builder description(String description) {
+            this.description = description;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.UrlMapTest#getHost()
+          */
+         public Builder host(String host) {
+            this.host = host;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.UrlMapTest#getPath()
+          */
+         public Builder path(String path) {
+            this.path = path;
+            return this;
+         }
+         
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.UrlMap.UrlMapTest#getService()
+          */
+         public Builder service(URI service) {
+            this.service = service;
+            return this;
+         }
+         
+         public UrlMapTest build() {
+            return new UrlMapTest(description, host, path, service);
+         }
+         
+         public Builder fromTest(UrlMapTest urlMapTest) {
+            return new Builder().description(urlMapTest.getDescription().orNull())
+                                .host(urlMapTest.getHost())
+                                .path(urlMapTest.getPath())
+                                .service(urlMapTest.getService());
+         }
+      }
+   }
+}
\ No newline at end of file