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/09/06 19:39:50 UTC

[01/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Updated Branches:
  refs/heads/master 2c45acab6 -> 533863808


http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/machinetype_list_central1b.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/machinetype_list_central1b.json b/google-compute-engine/src/test/resources/machinetype_list_central1b.json
new file mode 100644
index 0000000..cba2adf
--- /dev/null
+++ b/google-compute-engine/src/test/resources/machinetype_list_central1b.json
@@ -0,0 +1,43 @@
+{
+   "kind": "compute#machineTypeList",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/abayer-jclouds-test1/zones/us-central1-b/machineTypes",
+   "id": "projects/abayer-jclouds-test1/zones/us-central1-b/machineTypes",
+   "items": [
+      {
+         "kind": "compute#machineType",
+         "id": "12907738072351752276",
+         "creationTimestamp": "2012-06-07T20:48:14.670",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b/machineTypes/n1-standard-0",
+         "name": "n1-standard-0",
+         "description": "1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk",
+         "guestCpus": 1,
+         "memoryMb": 3840,
+         "imageSpaceGb": 10,
+         "maximumPersistentDisks": 16,
+         "maximumPersistentDisksSizeGb": "128",
+         "zone": "us-central1-b"
+      },
+      {
+         "kind": "compute#machineType",
+         "id": "12908560709887590691",
+         "creationTimestamp": "2012-06-07T20:51:19.936",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b/machineTypes/n1-standard-8-d",
+         "name": "n1-standard-8-d",
+         "description": "8 vCPUs, 30 GB RAM, a 10 GB ephemeral root disk, and 2 extra 1770 GB ephemeral disks",
+         "guestCpus": 8,
+         "memoryMb": 30720,
+         "imageSpaceGb": 10,
+         "scratchDisks": [
+            {
+               "diskGb": 1770
+            },
+            {
+               "diskGb": 1770
+            }
+         ],
+         "maximumPersistentDisks": 16,
+         "maximumPersistentDisksSizeGb": "1024",
+         "zone": "us-central1-b"
+      }
+      ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/machinetype_list_central1b_empty.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/machinetype_list_central1b_empty.json b/google-compute-engine/src/test/resources/machinetype_list_central1b_empty.json
new file mode 100644
index 0000000..793c9eb
--- /dev/null
+++ b/google-compute-engine/src/test/resources/machinetype_list_central1b_empty.json
@@ -0,0 +1,6 @@
+{
+   "kind": "compute#machineTypeList",
+   "id": "projects/myproject/zones/us-central1-b/machineTypes",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b/machineTypes",
+   "items": []
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/metadata.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/metadata.json b/google-compute-engine/src/test/resources/metadata.json
index 6901331..5014270 100644
--- a/google-compute-engine/src/test/resources/metadata.json
+++ b/google-compute-engine/src/test/resources/metadata.json
@@ -1 +1 @@
-{"kind":"compute#metadata","items":[{"key":"propA","value":"valueA"},{"key":"propB","value":"valueB"}]}
\ No newline at end of file
+{"kind":"compute#metadata","items":[{"key":"propA","value":"valueA"},{"key":"propB","value":"valueB"}],"fingerprint":"efgh"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/network_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/network_get.json b/google-compute-engine/src/test/resources/network_get.json
index 1a6a4b1..87f9e56 100644
--- a/google-compute-engine/src/test/resources/network_get.json
+++ b/google-compute-engine/src/test/resources/network_get.json
@@ -1,10 +1,10 @@
 {
- "kind": "compute#network",
- "id": "13024414170909937976",
- "creationTimestamp": "2012-10-24T20:13:19.967",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
- "name": "default",
- "description": "Default network for the project",
- "IPv4Range": "10.0.0.0/8",
- "gatewayIPv4": "10.0.0.1"
+   "kind": "compute#network",
+   "id": "13024414170909937976",
+   "creationTimestamp": "2012-10-24T20:13:19.967",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/networks/jclouds-test",
+   "name": "default",
+   "description": "Default network for the project",
+   "IPv4Range": "10.0.0.0/8",
+   "gatewayIPv4": "10.0.0.1"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/network_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/network_list.json b/google-compute-engine/src/test/resources/network_list.json
index 99ccc49..1cb72a1 100644
--- a/google-compute-engine/src/test/resources/network_list.json
+++ b/google-compute-engine/src/test/resources/network_list.json
@@ -1,18 +1,18 @@
 {
- "kind": "compute#networkList",
- "id": "projects/myproject/networks",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks",
- "items": [
-  {
+   "kind": "compute#networkList",
+   "id": "projects/myproject/networks",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/networks",
+   "items": [
+      {
 
-   "kind": "compute#network",
-   "id": "13024414170909937976",
-   "creationTimestamp": "2012-10-24T20:13:19.967",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
-   "name": "default",
-   "description": "Default network for the project",
-   "IPv4Range": "10.0.0.0/8",
-   "gatewayIPv4": "10.0.0.1"
-  }
- ]
+         "kind": "compute#network",
+         "id": "13024414170909937976",
+         "creationTimestamp": "2012-10-24T20:13:19.967",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/networks/jclouds-test",
+         "name": "default",
+         "description": "Default network for the project",
+         "IPv4Range": "10.0.0.0/8",
+         "gatewayIPv4": "10.0.0.1"
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/operation.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/operation.json b/google-compute-engine/src/test/resources/operation.json
index 68b16fb..e173bac 100644
--- a/google-compute-engine/src/test/resources/operation.json
+++ b/google-compute-engine/src/test/resources/operation.json
@@ -1,9 +1,9 @@
 {
    "kind": "compute#operation",
    "id": "13053095055850848306",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
    "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
-   "targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
    "targetId": "13053094017547040099",
    "status": "DONE",
    "user": "user@developer.gserviceaccount.com",
@@ -11,5 +11,7 @@
    "insertTime": "2012-11-28T06:41:05.060",
    "startTime": "2012-11-28T06:41:05.142",
    "endTime": "2012-11-28T06:41:06.142",
-   "operationType": "insert"
-  }
\ No newline at end of file
+   "operationType": "insert",
+   "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/operation_error.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/operation_error.json b/google-compute-engine/src/test/resources/operation_error.json
index f7f8e23..b18ffba 100644
--- a/google-compute-engine/src/test/resources/operation_error.json
+++ b/google-compute-engine/src/test/resources/operation_error.json
@@ -1,9 +1,9 @@
 {
    "kind": "compute#operation",
    "id": "13053095055850848306",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
    "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
-   "targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
    "targetId": "13053094017547040099",
    "status": "DONE",
    "user": "user@developer.gserviceaccount.com",
@@ -13,12 +13,14 @@
    "httpErrorStatusCode": 400,
    "httpErrorMessage": "BAD REQUEST",
    "error": {
-    "errors": [
-     {
-      "code": "RESOURCE_ALREADY_EXISTS",
-      "message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
-     }
-    ]
+      "errors": [
+         {
+            "code": "RESOURCE_ALREADY_EXISTS",
+            "message": "The resource 'projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance' already exists"
+         }
+      ]
    },
-   "operationType": "insert"
-  }
\ No newline at end of file
+   "operationType": "insert",
+   "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/operation_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/operation_list.json b/google-compute-engine/src/test/resources/operation_list.json
index 8bc3111..7585099 100644
--- a/google-compute-engine/src/test/resources/operation_list.json
+++ b/google-compute-engine/src/test/resources/operation_list.json
@@ -1,22 +1,24 @@
 {
- "kind": "compute#operationList",
- "id": "projects/myproject/operations",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations",
- "items": [
-  {
-     "kind": "compute#operation",
-     "id": "13053095055850848306",
-     "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
-     "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
-     "targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
-     "targetId": "13053094017547040099",
-     "status": "DONE",
-     "user": "user@developer.gserviceaccount.com",
-     "progress": 100,
-     "insertTime": "2012-11-28T06:41:05.060",
-     "startTime": "2012-11-28T06:41:05.142",
-     "endTime": "2012-11-28T06:41:06.142",
-     "operationType": "insert"
-    }
- ]
+   "kind": "compute#operationList",
+   "id": "projects/myproject/operations",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/operations",
+   "items": [
+      {
+         "kind": "compute#operation",
+         "id": "13053095055850848306",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
+         "targetId": "13053094017547040099",
+         "status": "DONE",
+         "user": "user@developer.gserviceaccount.com",
+         "progress": 100,
+         "insertTime": "2012-11-28T06:41:05.060",
+         "startTime": "2012-11-28T06:41:05.142",
+         "endTime": "2012-11-28T06:41:06.142",
+         "operationType": "insert",
+         "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+         "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/project.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/project.json b/google-compute-engine/src/test/resources/project.json
index 6129ac4..cef57d8 100644
--- a/google-compute-engine/src/test/resources/project.json
+++ b/google-compute-engine/src/test/resources/project.json
@@ -1,68 +1,69 @@
 {
- "kind": "compute#project",
- "id": "13024414184846275913",
- "creationTimestamp": "2012-10-24T20:13:16.252",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject",
- "name": "myproject",
- "description": "",
- "commonInstanceMetadata": {
-  "kind": "compute#metadata",
-  "items": [
-   {
-    "key": "propA",
-    "value": "valueA"
+   "kind": "compute#project",
+   "id": "13024414184846275913",
+   "creationTimestamp": "2012-10-24T20:13:16.252",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject",
+   "name": "myproject",
+   "description": "",
+   "commonInstanceMetadata": {
+      "kind": "compute#metadata",
+      "items": [
+         {
+            "key": "propA",
+            "value": "valueA"
+         },
+         {
+            "key": "propB",
+            "value": "valueB"
+         }
+      ],
+       "fingerprint": "efgh"
    },
-   {
-    "key": "propB",
-    "value": "valueB"
-   }
-  ]
- },
- "quotas": [
-  {
-   "metric": "INSTANCES",
-   "usage": 0,
-   "limit": 8
-  },
-  {
-   "metric": "CPUS",
-   "usage": 0,
-   "limit": 8
-  },
-  {
-   "metric": "EPHEMERAL_ADDRESSES",
-   "usage": 0,
-   "limit": 8
-  },
-  {
-   "metric": "DISKS",
-   "usage": 0,
-   "limit": 8
-  },
-  {
-   "metric": "DISKS_TOTAL_GB",
-   "usage": 0,
-   "limit": 100
-  },
-  {
-   "metric": "SNAPSHOTS",
-   "usage": 0,
-   "limit": 1000
-  },
-  {
-   "metric": "NETWORKS",
-   "usage": 1,
-   "limit": 5
-  },
-  {
-   "metric": "FIREWALLS",
-   "usage": 2,
-   "limit": 100
-  },
-  {
-   "metric": "IMAGES",
-   "usage": 0,
-   "limit": 100
-  }
- ]
+   "quotas": [
+      {
+         "metric": "INSTANCES",
+         "usage": 0,
+         "limit": 8
+      },
+      {
+         "metric": "CPUS",
+         "usage": 0,
+         "limit": 8
+      },
+      {
+         "metric": "EPHEMERAL_ADDRESSES",
+         "usage": 0,
+         "limit": 8
+      },
+      {
+         "metric": "DISKS",
+         "usage": 0,
+         "limit": 8
+      },
+      {
+         "metric": "DISKS_TOTAL_GB",
+         "usage": 0,
+         "limit": 100
+      },
+      {
+         "metric": "SNAPSHOTS",
+         "usage": 0,
+         "limit": 1000
+      },
+      {
+         "metric": "NETWORKS",
+         "usage": 1,
+         "limit": 5
+      },
+      {
+         "metric": "FIREWALLS",
+         "usage": 2,
+         "limit": 100
+      },
+      {
+         "metric": "IMAGES",
+         "usage": 0,
+         "limit": 100
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/region_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/region_get.json b/google-compute-engine/src/test/resources/region_get.json
new file mode 100644
index 0000000..f48e6de
--- /dev/null
+++ b/google-compute-engine/src/test/resources/region_get.json
@@ -0,0 +1,13 @@
+{
+    "kind": "compute#region",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+    "id": "12912210600542709766",
+    "creationTimestamp": "2013-07-08T14:40:37.939-07:00",
+    "name": "us-central1",
+    "description": "us-central1",
+    "status": "UP",
+    "zones": [
+        "https://www.googleapis.com/compute/v1beta15/zones/us-central1-a",
+        "https://www.googleapis.com/compute/v1beta15/zones/us-central1-b"
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/region_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/region_list.json b/google-compute-engine/src/test/resources/region_list.json
new file mode 100644
index 0000000..6e5df45
--- /dev/null
+++ b/google-compute-engine/src/test/resources/region_list.json
@@ -0,0 +1,32 @@
+{
+    "kind": "compute#regionList",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions",
+    "id": "projects/myproject/regions",
+    "items": [
+        {
+            "kind": "compute#region",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+            "id": "12912210600542709766",
+            "creationTimestamp": "2013-07-08T14:40:37.939-07:00",
+            "name": "us-central1",
+            "description": "us-central1",
+            "status": "UP",
+            "zones": [
+                "https://www.googleapis.com/compute/v1beta15/zones/us-central1-a",
+                "https://www.googleapis.com/compute/v1beta15/zones/us-central1-b"
+            ]
+        },
+        {
+            "kind": "compute#region",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central2",
+            "id": "6396763663251190992",
+            "creationTimestamp": "2013-07-08T14:40:37.939-07:00",
+            "name": "us-central2",
+            "description": "us-central2",
+            "status": "UP",
+            "zones": [
+                "https://www.googleapis.com/compute/v1beta15/zones/us-central2-a"
+            ]
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/region_operation.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/region_operation.json b/google-compute-engine/src/test/resources/region_operation.json
new file mode 100644
index 0000000..738e176
--- /dev/null
+++ b/google-compute-engine/src/test/resources/region_operation.json
@@ -0,0 +1,16 @@
+{
+   "kind": "compute#operation",
+   "id": "13053095055850848306",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-address",
+   "targetId": "13053094017547040099",
+   "status": "DONE",
+   "user": "user@developer.gserviceaccount.com",
+   "progress": 100,
+   "insertTime": "2012-11-28T06:41:05.060",
+   "startTime": "2012-11-28T06:41:05.142",
+   "endTime": "2012-11-28T06:41:06.142",
+   "operationType": "insert",
+   "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/region_operation_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/region_operation_list.json b/google-compute-engine/src/test/resources/region_operation_list.json
new file mode 100644
index 0000000..047d12f
--- /dev/null
+++ b/google-compute-engine/src/test/resources/region_operation_list.json
@@ -0,0 +1,23 @@
+{
+   "kind": "compute#operationList",
+   "id": "projects/myproject/regions/us-central1/operations",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/operations",
+   "items": [
+      {
+         "kind": "compute#operation",
+         "id": "13053095055850848306",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-address",
+         "targetId": "13053094017547040099",
+         "status": "DONE",
+         "user": "user@developer.gserviceaccount.com",
+         "progress": 100,
+         "insertTime": "2012-11-28T06:41:05.060",
+         "startTime": "2012-11-28T06:41:05.142",
+         "endTime": "2012-11-28T06:41:06.142",
+         "operationType": "insert",
+         "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"
+      }
+   ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/route_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/route_get.json b/google-compute-engine/src/test/resources/route_get.json
new file mode 100644
index 0000000..994f0b1
--- /dev/null
+++ b/google-compute-engine/src/test/resources/route_get.json
@@ -0,0 +1,14 @@
+{
+
+    "kind": "compute#route",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375",
+    "id": "7241926205630356071",
+    "creationTimestamp": "2013-07-08T14:40:38.502-07:00",
+    "name": "default-route-c99ebfbed0e1f375",
+    "description": "Default route to the virtual network.",
+    "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default",
+    "destRange": "10.240.0.0/16",
+    "priority": 1000,
+    "nextHopNetwork": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default",
+    "tags": [ "fooTag", "barTag" ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/route_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/route_insert.json b/google-compute-engine/src/test/resources/route_insert.json
new file mode 100644
index 0000000..6f0bc30
--- /dev/null
+++ b/google-compute-engine/src/test/resources/route_insert.json
@@ -0,0 +1 @@
+{"name":"default-route-c99ebfbed0e1f375","description":"Default route to the virtual network.","network":"https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default","destRange":"10.240.0.0/16","priority":1000,"nextHopNetwork":"https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default","tags":["fooTag","barTag"]}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/route_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/route_list.json b/google-compute-engine/src/test/resources/route_list.json
new file mode 100644
index 0000000..a8ffc2e
--- /dev/null
+++ b/google-compute-engine/src/test/resources/route_list.json
@@ -0,0 +1,34 @@
+{
+    "kind": "compute#routeList",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes",
+    "id": "projects/myproject/global/routes",
+    "items": [
+        {
+
+            "kind": "compute#route",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375",
+            "id": "7241926205630356071",
+            "creationTimestamp": "2013-07-08T14:40:38.502-07:00",
+            "name": "default-route-c99ebfbed0e1f375",
+            "description": "Default route to the virtual network.",
+            "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default",
+            "destRange": "10.240.0.0/16",
+            "priority": 1000,
+            "nextHopNetwork": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default",
+            "tags": [ "fooTag", "barTag" ]
+        },
+        {
+
+            "kind": "compute#route",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-fc92a41ecb5a8d17",
+            "id": "507025480040058551",
+            "creationTimestamp": "2013-07-08T14:40:38.502-07:00",
+            "name": "default-route-fc92a41ecb5a8d17",
+            "description": "Default route to the Internet.",
+            "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default",
+            "destRange": "0.0.0.0/0",
+            "priority": 1000,
+            "nextHopGateway": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/gateways/default-internet-gateway"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/snapshot_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/snapshot_get.json b/google-compute-engine/src/test/resources/snapshot_get.json
new file mode 100644
index 0000000..6ec8ee4
--- /dev/null
+++ b/google-compute-engine/src/test/resources/snapshot_get.json
@@ -0,0 +1,13 @@
+{
+
+    "kind": "compute#snapshot",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots/test-snap",
+    "id": "9734455566806191190",
+    "creationTimestamp": "2013-07-26T12:54:23.173-07:00",
+    "status": "READY",
+    "diskSizeGb": "10",
+    "sourceDisk": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+    "name": "test-snap",
+    "description": "",
+    "sourceDiskId": "8243603669926824540"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/snapshot_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/snapshot_list.json b/google-compute-engine/src/test/resources/snapshot_list.json
new file mode 100644
index 0000000..9db2e3d
--- /dev/null
+++ b/google-compute-engine/src/test/resources/snapshot_list.json
@@ -0,0 +1,33 @@
+{
+    "kind": "compute#snapshotList",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots",
+    "id": "projects/myproject/global/snapshots",
+    "items": [
+        {
+
+            "kind": "compute#snapshot",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots/test-snap",
+            "id": "9734455566806191190",
+            "creationTimestamp": "2013-07-26T12:54:23.173-07:00",
+            "status": "READY",
+            "diskSizeGb": "10",
+            "sourceDisk": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+            "name": "test-snap",
+            "description": "",
+            "sourceDiskId": "8243603669926824540"
+        },
+        {
+
+            "kind": "compute#snapshot",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots/test-snap2",
+            "id": "13895715048576107883",
+            "creationTimestamp": "2013-07-26T12:57:01.927-07:00",
+            "status": "READY",
+            "diskSizeGb": "10",
+            "sourceDisk": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+            "name": "test-snap2",
+            "description": "",
+            "sourceDiskId": "8243603669926824540"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/tag_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/tag_insert.json b/google-compute-engine/src/test/resources/tag_insert.json
new file mode 100644
index 0000000..61ade71
--- /dev/null
+++ b/google-compute-engine/src/test/resources/tag_insert.json
@@ -0,0 +1 @@
+{"items":["aTag"],"fingerprint":"abcd"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_get.json b/google-compute-engine/src/test/resources/zone_get.json
index cf3dc09..c64aeee 100644
--- a/google-compute-engine/src/test/resources/zone_get.json
+++ b/google-compute-engine/src/test/resources/zone_get.json
@@ -1,17 +1,17 @@
 {
- "kind": "compute#zone",
- "id": "13020128040171887099",
- "creationTimestamp": "2012-10-19T16:42:54.131",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
- "name": "us-central1-a",
- "description": "us-central1-a",
- "status": "DOWN",
- "maintenanceWindows": [
-  {
-   "name": "2012-11-10-planned-outage",
-   "description": "maintenance zone",
-   "beginTime": "2012-11-10T20:00:00.000",
-   "endTime": "2012-12-02T20:00:00.000"
-  }
- ]
+   "kind": "compute#zone",
+   "id": "13020128040171887099",
+   "creationTimestamp": "2012-10-19T16:42:54.131",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+   "name": "us-central1-a",
+   "description": "us-central1-a",
+   "status": "DOWN",
+   "maintenanceWindows": [
+      {
+         "name": "2012-11-10-planned-outage",
+         "description": "maintenance zone",
+         "beginTime": "2012-11-10T20:00:00.000",
+         "endTime": "2012-12-02T20:00:00.000"
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_list.json b/google-compute-engine/src/test/resources/zone_list.json
index 8d11f0d..fb1a6df 100644
--- a/google-compute-engine/src/test/resources/zone_list.json
+++ b/google-compute-engine/src/test/resources/zone_list.json
@@ -1,41 +1,41 @@
 {
- "kind": "compute#zoneList",
- "id": "projects/myproject/zones",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones",
- "items": [
-  {
-   "kind": "compute#zone",
-   "id": "13020128040171887099",
-   "creationTimestamp": "2012-10-19T16:42:54.131",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
-   "name": "us-central1-a",
-   "description": "us-central1-a",
-   "status": "DOWN",
-   "maintenanceWindows": [
-    {
-     "name": "2012-11-10-planned-outage",
-     "description": "maintenance zone",
-     "beginTime": "2012-11-10T20:00:00.000",
-     "endTime": "2012-12-02T20:00:00.000"
-    }
+   "kind": "compute#zoneList",
+   "id": "projects/myproject/zones",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones",
+   "items": [
+      {
+         "kind": "compute#zone",
+         "id": "13020128040171887099",
+         "creationTimestamp": "2012-10-19T16:42:54.131",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+         "name": "us-central1-a",
+         "description": "us-central1-a",
+         "status": "DOWN",
+         "maintenanceWindows": [
+            {
+               "name": "2012-11-10-planned-outage",
+               "description": "maintenance zone",
+               "beginTime": "2012-11-10T20:00:00.000",
+               "endTime": "2012-12-02T20:00:00.000"
+            }
+         ]
+      },
+      {
+         "kind": "compute#zone",
+         "id": "13024414164050619686",
+         "creationTimestamp": "2012-10-24T20:13:19.271",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b",
+         "name": "us-central1-b",
+         "description": "us-central1-b",
+         "status": "UP",
+         "maintenanceWindows": [
+            {
+               "name": "2013-02-17-planned-outage",
+               "description": "maintenance zone",
+               "beginTime": "2013-02-17T08:00:00.000",
+               "endTime": "2013-03-03T08:00:00.000"
+            }
+         ]
+      }
    ]
-  },
-  {
-   "kind": "compute#zone",
-   "id": "13024414164050619686",
-   "creationTimestamp": "2012-10-24T20:13:19.271",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-east1-a",
-   "name": "us-east1-a",
-   "description": "us-east1-a",
-   "status": "UP",
-   "maintenanceWindows": [
-    {
-     "name": "2013-02-17-planned-outage",
-     "description": "maintenance zone",
-     "beginTime": "2013-02-17T08:00:00.000",
-     "endTime": "2013-03-03T08:00:00.000"
-    }
-   ]
-  }
- ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_list_short.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_list_short.json b/google-compute-engine/src/test/resources/zone_list_short.json
new file mode 100644
index 0000000..5512aa0
--- /dev/null
+++ b/google-compute-engine/src/test/resources/zone_list_short.json
@@ -0,0 +1,24 @@
+{
+   "kind": "compute#zoneList",
+   "id": "projects/myproject/zones",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones",
+   "items": [
+      {
+         "kind": "compute#zone",
+         "id": "13020128040171887099",
+         "creationTimestamp": "2012-10-19T16:42:54.131",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+         "name": "us-central1-a",
+         "description": "us-central1-a",
+         "status": "DOWN",
+         "maintenanceWindows": [
+            {
+               "name": "2012-11-10-planned-outage",
+               "description": "maintenance zone",
+               "beginTime": "2012-11-10T20:00:00.000",
+               "endTime": "2012-12-02T20:00:00.000"
+            }
+         ]
+      }
+   ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_operation.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_operation.json b/google-compute-engine/src/test/resources/zone_operation.json
new file mode 100644
index 0000000..ab93cb9
--- /dev/null
+++ b/google-compute-engine/src/test/resources/zone_operation.json
@@ -0,0 +1,16 @@
+{
+   "kind": "compute#operation",
+   "id": "13053095055850848306",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
+   "targetId": "13053094017547040099",
+   "status": "DONE",
+   "user": "user@developer.gserviceaccount.com",
+   "progress": 100,
+   "insertTime": "2012-11-28T06:41:05.060",
+   "startTime": "2012-11-28T06:41:05.142",
+   "endTime": "2012-11-28T06:41:06.142",
+   "operationType": "insert",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_operation_error.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_operation_error.json b/google-compute-engine/src/test/resources/zone_operation_error.json
new file mode 100644
index 0000000..10b5477
--- /dev/null
+++ b/google-compute-engine/src/test/resources/zone_operation_error.json
@@ -0,0 +1,25 @@
+{
+   "kind": "compute#operation",
+   "id": "13053095055850848306",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
+   "targetId": "13053094017547040099",
+   "status": "DONE",
+   "user": "user@developer.gserviceaccount.com",
+   "progress": 100,
+   "insertTime": "2012-11-28T06:41:05.060",
+   "startTime": "2012-11-28T06:41:05.142",
+   "httpErrorStatusCode": 400,
+   "httpErrorMessage": "BAD REQUEST",
+   "error": {
+      "errors": [
+         {
+            "code": "RESOURCE_ALREADY_EXISTS",
+            "message": "The resource 'projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance' already exists"
+         }
+      ]
+   },
+   "operationType": "insert",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/zone_operation_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/zone_operation_list.json b/google-compute-engine/src/test/resources/zone_operation_list.json
new file mode 100644
index 0000000..7a3137a
--- /dev/null
+++ b/google-compute-engine/src/test/resources/zone_operation_list.json
@@ -0,0 +1,23 @@
+{
+   "kind": "compute#operationList",
+   "id": "projects/myproject/zones/us-central1-a/operations",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations",
+   "items": [
+      {
+         "kind": "compute#operation",
+         "id": "13053095055850848306",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance",
+         "targetId": "13053094017547040099",
+         "status": "DONE",
+         "user": "user@developer.gserviceaccount.com",
+         "progress": 100,
+         "insertTime": "2012-11-28T06:41:05.060",
+         "startTime": "2012-11-28T06:41:05.142",
+         "endTime": "2012-11-28T06:41:06.142",
+         "operationType": "insert",
+         "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"
+      }
+   ]
+}
\ No newline at end of file


[10/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
deleted file mode 100644
index 410c7ea..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeToHardware.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.googlecomputeengine.compute.functions;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.HardwareBuilder;
-import org.jclouds.compute.domain.Processor;
-import org.jclouds.compute.domain.Volume;
-import org.jclouds.compute.domain.internal.VolumeImpl;
-import org.jclouds.googlecomputeengine.domain.MachineType;
-
-/**
- * Transforms a google compute domain specific machine type to a generic Hardware object.
- *
- * @author David Alves
- */
-public class MachineTypeToHardware implements Function<MachineType, Hardware> {
-
-   @Override
-   public Hardware apply(MachineType input) {
-      return new HardwareBuilder()
-              .id(input.getName())
-              .name(input.getName())
-              .hypervisor("kvm")
-              .processor(new Processor(input.getGuestCpus(), 1.0))
-              .providerId(input.getId())
-              .ram(input.getMemoryMb())
-              .uri(input.getSelfLink())
-              .volumes(collectVolumes(input))
-              .build();
-   }
-
-   private Iterable<Volume> collectVolumes(MachineType input) {
-      ImmutableSet.Builder<Volume> volumes = ImmutableSet.builder();
-      for (MachineType.EphemeralDisk disk : input.getEphemeralDisks()) {
-         volumes.add(new VolumeImpl(null, Volume.Type.LOCAL, new Integer(disk.getDiskGb()).floatValue(), null, true,
-                 false));
-      }
-      return volumes.build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java
index 9314298..f919697 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java
@@ -16,14 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Sets;
-import org.jclouds.compute.domain.NodeMetadata;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import java.util.Set;
+
+import org.jclouds.compute.domain.NodeMetadata;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Sets;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java
new file mode 100644
index 0000000..c878688
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
+
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.googlecomputeengine.domain.Region;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Transforms a google compute domain specific region to a generic Region object.
+ *
+ * @author David Alves
+ */
+public class RegionToLocation implements Function<Region, Location> {
+
+   @Override
+   public Location apply(Region input) {
+      return new LocationBuilder()
+              .description(input.getDescription().orNull())
+              .metadata(ImmutableMap.of("selfLink", (Object) checkNotNull(input.getSelfLink(), "region URI")))
+              .id(input.getName())
+              .scope(LocationScope.REGION)
+              .parent(GOOGLE_PROVIDER_LOCATION)
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java
index 56dde56..be2df66 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
+
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.googlecomputeengine.domain.Zone;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * Transforms a google compute domain specific zone to a generic Zone object.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
index 9d74d3c..b5d74ed 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.compute.options;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.LoginCredentials;
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.scriptbuilder.domain.Statement;
+import static com.google.common.base.Optional.fromNullable;
+import static org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
 
 import java.net.URI;
 import java.util.Map;
 import java.util.Set;
 
-import static com.google.common.base.Optional.fromNullable;
-import static org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 /**
  * Instance options specific to Google Compute Engine.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java
index 72d0371..a52f9b0 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java
@@ -16,12 +16,6 @@
  */
 package org.jclouds.googlecomputeengine.compute.predicates;
 
-import com.google.common.base.Predicate;
-import org.jclouds.compute.ComputeService;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.all;
 import static com.google.common.collect.Sets.filter;
@@ -29,6 +23,13 @@ import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
 import static org.jclouds.compute.predicates.NodePredicates.all;
 import static org.jclouds.compute.predicates.NodePredicates.inGroup;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.ComputeService;
+
+import com.google.common.base.Predicate;
+
 /**
  * @author David Alves
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
index b680607..5380313 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -16,12 +16,21 @@
  */
 package org.jclouds.googlecomputeengine.compute.strategy;
 
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableSet.of;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
 import org.jclouds.Constants;
 import org.jclouds.compute.config.CustomizationResponse;
 import org.jclouds.compute.domain.NodeMetadata;
@@ -38,19 +47,12 @@ import org.jclouds.googlecomputeengine.domain.Network;
 import org.jclouds.googlecomputeengine.domain.Operation;
 import org.jclouds.googlecomputeengine.options.FirewallOptions;
 
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableSet.of;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
-import static org.jclouds.util.Predicates2.retry;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
  * @author David Alves
@@ -78,7 +80,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
                    customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
            GoogleComputeEngineApi api,
            @UserProject Supplier<String> userProject,
-           Predicate<AtomicReference<Operation>> operationDonePredicate,
+           @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate,
            @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
            @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
       super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
@@ -127,7 +129,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
       if (network != null) {
          return network;
       } else if (templateOptions.getNetwork().isPresent()) {
-         throw new IllegalArgumentException("requested network " + networkName + " does not exist"); 
+         throw new IllegalArgumentException("requested network " + networkName + " does not exist");
       }
 
       AtomicReference<Operation> operation = new AtomicReference<Operation>(api.getNetworkApiForProject(userProject
@@ -135,7 +137,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
       retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
               MILLISECONDS).apply(operation);
 
-      checkState(!operation.get().getHttpError().isPresent(),"Could not create network, operation failed" + operation);
+      checkState(!operation.get().getHttpError().isPresent(), "Could not create network, operation failed" + operation);
 
       return checkNotNull(api.getNetworkApiForProject(userProject.get()).get(sharedResourceName),
               "no network with name %s was found", sharedResourceName);
@@ -186,7 +188,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
       retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
               MILLISECONDS).apply(operation);
 
-      checkState(!operation.get().getHttpError().isPresent(),"Could not create firewall, operation failed" + operation);
+      checkState(!operation.get().getHttpError().isPresent(), "Could not create firewall, operation failed" + operation);
    }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
index 38cfcf0..cdae3c4 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
@@ -16,19 +16,21 @@
  */
 package org.jclouds.googlecomputeengine.compute.strategy;
 
-import com.google.inject.Inject;
-import org.jclouds.compute.domain.TemplateBuilderSpec;
-import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
 
 import javax.annotation.PostConstruct;
 import javax.inject.Named;
 import javax.inject.Singleton;
-import java.security.NoSuchAlgorithmException;
-import java.util.Map;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
+
+import com.google.inject.Inject;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
index dcad62c..d774b55 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.compute.strategy;
 
-import com.google.common.base.Function;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.options.RunScriptOptions;
 import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
 import org.jclouds.domain.LoginCredentials;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 /**
  * GCE needs the credentials to create the node so the node credentials already take the Image credentials into account,

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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 6c393f4..31f3786 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
@@ -18,8 +18,11 @@ package org.jclouds.googlecomputeengine.config;
 
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Suppliers.compose;
+import static com.google.inject.name.Names.named;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
 
 import java.net.URI;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.inject.Named;
@@ -28,8 +31,12 @@ import javax.inject.Singleton;
 import org.jclouds.domain.Credentials;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Project;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
 import org.jclouds.googlecomputeengine.handlers.GoogleComputeEngineErrorHandler;
-import org.jclouds.googlecomputeengine.predicates.OperationDonePredicate;
+import org.jclouds.googlecomputeengine.predicates.GlobalOperationDonePredicate;
+import org.jclouds.googlecomputeengine.predicates.RegionOperationDonePredicate;
+import org.jclouds.googlecomputeengine.predicates.ZoneOperationDonePredicate;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.Uris;
 import org.jclouds.http.annotation.ClientError;
@@ -38,8 +45,12 @@ import org.jclouds.http.annotation.ServerError;
 import org.jclouds.json.config.GsonModule.DateAdapter;
 import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
 import org.jclouds.location.Provider;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.implicit.FirstZone;
+import org.jclouds.rest.AuthorizationException;
 import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -47,6 +58,7 @@ import com.google.common.base.Splitter;
 import com.google.common.base.Supplier;
 import com.google.common.collect.Iterables;
 import com.google.inject.Provides;
+import com.google.inject.Scopes;
 import com.google.inject.TypeLiteral;
 
 /**
@@ -62,7 +74,13 @@ public class GoogleComputeEngineHttpApiModule extends HttpApiModule<GoogleComput
    @Override
    protected void configure() {
       bind(DateAdapter.class).to(Iso8601DateAdapter.class);
-      bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {}).to(OperationDonePredicate.class);
+      bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }).annotatedWith(named("global")).to(GlobalOperationDonePredicate.class);
+      bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }).annotatedWith(named("region")).to(RegionOperationDonePredicate.class);
+      bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }).annotatedWith(named("zone")).to(ZoneOperationDonePredicate.class);
+      bind(ImplicitLocationSupplier.class).to(FirstZone.class).in(Scopes.SINGLETON);
       super.configure();
    }
 
@@ -76,54 +94,76 @@ public class GoogleComputeEngineHttpApiModule extends HttpApiModule<GoogleComput
    @Provides
    @Singleton
    @UserProject
-   public Supplier<String> supplyProject(@org.jclouds.location.Provider final Supplier<Credentials> creds) {
-      return compose(new Function<Credentials, String>() {
-         public String apply(Credentials in) {
-            checkState(in.identity.indexOf("@") != 1, "identity should be in project_id@developer.gserviceaccount.com" +
-                    " format");
-            return Iterables.get(Splitter.on("@").split(in.identity), 0);
-         }
-      }, creds);
+   public Supplier<String> supplyProject(@Provider final Supplier<Credentials> creds,
+                                         final GoogleComputeEngineApi api,
+                                         AtomicReference<AuthorizationException> authException,
+                                         @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              compose(new Function<Credentials, String>() {
+                 public String apply(Credentials in) {
+                    checkState(in.identity.indexOf("@") != 1,
+                            "identity should be in project_id@developer.gserviceaccount.com format");
+
+                    Project project = api.getProjectApi().get(Iterables.get(Splitter.on("@").split(in.identity), 0));
+                    return project.getName();
+                 }
+              }, creds), seconds, TimeUnit.SECONDS);
    }
 
    @Provides
    @Singleton
-   @Named("machineTypes")
+   @Named("machineTypeToURI")
    public Function<String, URI> provideMachineTypeNameToURIFunction(final @Provider Supplier<URI> endpoint,
                                                                     final @UserProject Supplier<String> userProject) {
       return new Function<String, URI>() {
          @Override
          public URI apply(String input) {
-            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
-                    ("/machineTypes/").appendPath(input).build();
+            SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(input);
+            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+                    .appendPath("/zones/").appendPath(slashEncodedIds.getFirstId())
+                    .appendPath("/machineTypes/").appendPath(slashEncodedIds.getSecondId()).build();
          }
       };
    }
 
    @Provides
    @Singleton
-   @Named("networks")
+   @Named("networkToURI")
    public Function<String, URI> provideNetworkNameToURIFunction(final @Provider Supplier<URI> endpoint,
                                                                 final @UserProject Supplier<String> userProject) {
       return new Function<String, URI>() {
          @Override
          public URI apply(String input) {
-            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
-                    ("/networks/").appendPath(input).build();
+            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+                    .appendPath("/global/networks/").appendPath(input).build();
          }
       };
    }
 
    @Provides
    @Singleton
-   @Named("zones")
+   @Named("zoneToURI")
    public Function<String, URI> provideZoneNameToURIFunction(final @Provider Supplier<URI> endpoint,
                                                              final @UserProject Supplier<String> userProject) {
       return new Function<String, URI>() {
          @Override
          public URI apply(String input) {
-            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
-                    ("/zones/").appendPath(input).build();
+            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+                    .appendPath("/zones/").appendPath(input).build();
+         }
+      };
+   }
+
+   @Provides
+   @Singleton
+   @Named("regionToURI")
+   public Function<String, URI> provideRegionNameToURIFunction(final @Provider Supplier<URI> endpoint,
+                                                               final @UserProject Supplier<String> userProject) {
+      return new Function<String, URI>() {
+         @Override
+         public URI apply(String input) {
+            return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+                    .appendPath("/regions/").appendPath(input).build();
          }
       };
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
index 28ac2ea..1378a80 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
@@ -16,7 +16,31 @@
  */
 package org.jclouds.googlecomputeengine.config;
 
-import com.google.common.collect.ForwardingMap;
+import static org.jclouds.googlecomputeengine.domain.Firewall.Rule;
+
+import java.beans.ConstructorProperties;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
+import org.jclouds.googlecomputeengine.domain.Metadata;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Project;
+import org.jclouds.googlecomputeengine.options.FirewallOptions;
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.oauth.v2.domain.ClaimSet;
+import org.jclouds.oauth.v2.domain.Header;
+import org.jclouds.oauth.v2.json.ClaimSetTypeAdapter;
+import org.jclouds.oauth.v2.json.HeaderTypeAdapter;
+
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Range;
 import com.google.gson.JsonArray;
@@ -30,27 +54,6 @@ import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
-import org.jclouds.googlecomputeengine.domain.Firewall;
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
-import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.googlecomputeengine.domain.Project;
-import org.jclouds.googlecomputeengine.options.FirewallOptions;
-import org.jclouds.json.config.GsonModule;
-import org.jclouds.oauth.v2.domain.ClaimSet;
-import org.jclouds.oauth.v2.domain.Header;
-import org.jclouds.oauth.v2.json.ClaimSetTypeAdapter;
-import org.jclouds.oauth.v2.json.HeaderTypeAdapter;
-
-import javax.inject.Singleton;
-import java.beans.ConstructorProperties;
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.util.Date;
-import java.util.Map;
-import java.util.Set;
-
-import static org.jclouds.googlecomputeengine.domain.Firewall.Rule;
 
 /**
  * @author David Alves
@@ -74,6 +77,7 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
               .put(Instance.class, new InstanceTypeAdapter())
               .put(InstanceTemplate.class, new InstanceTemplateTypeAdapter())
               .put(FirewallOptions.class, new FirewallOptionsTypeAdapter())
+              .put(RouteOptions.class, new RouteOptionsTypeAdapter())
               .put(Rule.class, new RuleTypeAdapter())
               .build();
    }
@@ -81,7 +85,7 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
    /**
     * Parser for operations that unwraps errors avoiding an extra intermediate object.
     *
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/operations"/>
     */
    @Singleton
    private static class OperationTypeAdapter implements JsonDeserializer<Operation> {
@@ -107,16 +111,16 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
          @ConstructorProperties({
                  "id", "creationTimestamp", "selfLink", "name", "description", "targetLink", "targetId",
                  "clientOperationId", "status", "statusMessage", "user", "progress", "insertTime", "startTime",
-                 "endTime", "httpErrorStatusCode", "httpErrorMessage", "operationType"
+                 "endTime", "httpErrorStatusCode", "httpErrorMessage", "operationType", "region", "zone"
          })
          private OperationInternal(String id, Date creationTimestamp, URI selfLink, String name,
                                    String description, URI targetLink, String targetId, String clientOperationId,
                                    Status status, String statusMessage, String user, int progress, Date insertTime,
                                    Date startTime, Date endTime, int httpErrorStatusCode, String httpErrorMessage,
-                                   String operationType) {
+                                   String operationType, URI region, URI zone) {
             super(id, creationTimestamp, selfLink, name, description, targetLink, targetId, clientOperationId,
                     status, statusMessage, user, progress, insertTime, startTime, endTime, httpErrorStatusCode,
-                    httpErrorMessage, operationType, null);
+                    httpErrorMessage, operationType, null, region, zone);
          }
       }
    }
@@ -149,8 +153,11 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
 
          // deal with metadata
          if (src.getMetadata() != null && !src.getMetadata().isEmpty()) {
-            JsonObject metadata = (JsonObject) context.serialize(new Metadata(src.getMetadata()));
-            instance.add("metadata", metadata);
+            Metadata metadata = Metadata.builder()
+                    .items(src.getMetadata())
+                    .build();
+            JsonObject metadataJson = (JsonObject) context.serialize(metadata);
+            instance.add("metadata", metadataJson);
             return instance;
          }
 
@@ -162,9 +169,7 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
             super(template.getMachineType());
             name(template.getName());
             description(template.getDescription());
-            zone(template.getZone());
             image(template.getImage());
-            tags(template.getTags());
             serviceAccounts(template.getServiceAccounts());
             networkInterfaces(template.getNetworkInterfaces());
          }
@@ -205,7 +210,7 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
                  "status", "statusMessage", "zone", "networkInterfaces", "metadata", "serviceAccounts"
          })
          private InstanceInternal(String id, Date creationTimestamp, URI selfLink, String name, String description,
-                                  Set<String> tags, URI image, URI machineType, Status status, String statusMessage,
+                                  Tags tags, URI image, URI machineType, Status status, String statusMessage,
                                   URI zone, Set<NetworkInterface> networkInterfaces, Metadata metadata,
                                   Set<ServiceAccount> serviceAccounts) {
             super(id, creationTimestamp, selfLink, name, description, tags, image, machineType,
@@ -233,7 +238,11 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
                builder.put(object.get("key").getAsString(), object.get("value").getAsString());
             }
          }
-         return new Metadata(builder.build());
+         String fingerprint = null;
+         if (metadata.getAsJsonPrimitive("fingerprint") != null) {
+            fingerprint = metadata.getAsJsonPrimitive("fingerprint").getAsString();
+         }
+         return new Metadata(fingerprint, builder.build());
       }
 
       @Override
@@ -241,30 +250,21 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
          JsonObject metadataObject = new JsonObject();
          metadataObject.add("kind", new JsonPrimitive("compute#metadata"));
          JsonArray items = new JsonArray();
-         for (Map.Entry<String, String> entry : src.entrySet()) {
+         for (Map.Entry<String, String> entry : src.getItems().entrySet()) {
             JsonObject object = new JsonObject();
             object.addProperty("key", entry.getKey());
             object.addProperty("value", entry.getValue());
             items.add(object);
          }
          metadataObject.add("items", items);
+         if (src.getFingerprint() != null) {
+            metadataObject.addProperty("fingerprint", src.getFingerprint());
+         }
          return metadataObject;
       }
    }
 
-   public static class Metadata extends ForwardingMap<String, String> {
 
-      private final Map<String, String> delegate;
-
-      public Metadata(Map<String, String> delegate) {
-         this.delegate = delegate;
-      }
-
-      @Override
-      protected Map<String, String> delegate() {
-         return delegate;
-      }
-   }
 
    @Singleton
    private static class ProjectTypeAdapter implements JsonDeserializer<Project> {
@@ -322,6 +322,46 @@ public class GoogleComputeEngineParserModule extends AbstractModule {
       }
    }
 
+   @Singleton
+   private static class RouteOptionsTypeAdapter implements JsonSerializer<RouteOptions> {
+
+      @Override
+      public JsonElement serialize(RouteOptions src, Type typeOfSrc, JsonSerializationContext context) {
+         JsonObject route = new JsonObject();
+         if (src.getName() != null) {
+            route.addProperty("name", src.getName());
+         }
+         if (src.getNetwork() != null) {
+            route.addProperty("network", src.getNetwork().toString());
+         }
+         if (src.getNextHopGateway() != null) {
+            route.addProperty("nextHopGateway", src.getNextHopGateway().toString());
+         }
+         if (src.getNextHopInstance() != null) {
+            route.addProperty("nextHopInstance", src.getNextHopInstance().toString());
+         }
+         if (src.getNextHopNetwork() != null) {
+            route.addProperty("nextHopNetwork", src.getNextHopNetwork().toString());
+         }
+         if (src.getDestRange() != null) {
+            route.addProperty("destRange", src.getDestRange());
+         }
+         if (src.getDescription() != null) {
+            route.addProperty("description", src.getDescription());
+         }
+         if (src.getPriority() != null) {
+            route.addProperty("priority", src.getPriority());
+         }
+         if (src.getNextHopIp() != null) {
+            route.addProperty("nextHopIp", src.getNextHopIp());
+         }
+         if (!src.getTags().isEmpty()) {
+            route.add("tags", buildArrayOfStrings(src.getTags()));
+         }
+         return route;
+      }
+   }
+
    private static JsonArray buildArrayOfStrings(Set<String> strings) {
       JsonArray array = new JsonArray();
       for (String string : strings) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
index fa62625..f287fff 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
@@ -16,9 +16,6 @@
  */
 package org.jclouds.googlecomputeengine.config;
 
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.inject.TypeLiteral;
 import org.jclouds.oauth.v2.config.OAuthModule;
 import org.jclouds.oauth.v2.domain.OAuthCredentials;
 import org.jclouds.oauth.v2.domain.Token;
@@ -29,6 +26,10 @@ import org.jclouds.oauth.v2.functions.OAuthCredentialsSupplier;
 import org.jclouds.oauth.v2.functions.SignOrProduceMacForToken;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
 
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.inject.TypeLiteral;
+
 /**
  * Overrides OAuthModule leaving TypeAdapters bindings out.
  * <p/>
@@ -40,9 +41,13 @@ public class OAuthModuleWithoutTypeAdapters extends OAuthModule {
 
    @Override
    protected void configure() {
-      bind(new TypeLiteral<Function<byte[], byte[]>>() {}).to(SignOrProduceMacForToken.class);
-      bind(new TypeLiteral<Supplier<OAuthCredentials>>() {}).to(OAuthCredentialsSupplier.class);
-      bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() {}).to(BuildTokenRequest.class);
-      bind(new TypeLiteral<Function<TokenRequest, Token>>() {}).to(FetchToken.class);
+      bind(new TypeLiteral<Function<byte[], byte[]>>() {
+      }).to(SignOrProduceMacForToken.class);
+      bind(new TypeLiteral<Supplier<OAuthCredentials>>() {
+      }).to(OAuthCredentialsSupplier.class);
+      bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() {
+      }).to(BuildTokenRequest.class);
+      bind(new TypeLiteral<Function<TokenRequest, Token>>() {
+      }).to(FetchToken.class);
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
index 1fe04bc..226d6a1 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.config;
 
-import javax.inject.Qualifier;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import javax.inject.Qualifier;
+
 /**
  * Qualifies a property as the user's project id.
  *

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
new file mode 100644
index 0000000..fda65ec
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+/**
+ * A persistent disk resource
+ *
+ * @author David Alves
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/disks"/>
+ */
+@Beta
+public abstract class AbstractDisk extends Resource {
+
+   protected final Integer sizeGb;
+   protected final String status;
+
+   protected AbstractDisk(Kind kind, String id, Date creationTimestamp, URI selfLink, String name, String description,
+                        Integer sizeGb, String status) {
+      super(kind, id, creationTimestamp, selfLink, name, description);
+      this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
+      this.status = checkNotNull(status, "status of %s", name);
+   }
+
+   /**
+    * @return size of the persistent disk, specified in GB.
+    */
+   public int getSizeGb() {
+      return sizeGb;
+   }
+
+   /**
+    * @return the status of disk creation.
+    */
+   public String getStatus() {
+      return status;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("sizeGb", sizeGb)
+              .add("status", status);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromAbstractDisk(this);
+   }
+
+   public abstract static class Builder<T extends Builder<T>> extends Resource.Builder<T> {
+
+      protected Integer sizeGb;
+      protected String status;
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.AbstractDisk#getSizeGb()
+       */
+      public T sizeGb(Integer sizeGb) {
+         this.sizeGb = sizeGb;
+         return self();
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.AbstractDisk#getStatus()
+       */
+      public T status(String status) {
+         this.status = status;
+         return self();
+      }
+
+      public T fromAbstractDisk(AbstractDisk in) {
+         return super.fromResource(in)
+                 .sizeGb(in.getSizeGb())
+                 .status(in.getStatus());
+      }
+
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
new file mode 100644
index 0000000..7f97ec0
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
@@ -0,0 +1,178 @@
+/*
+ * 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.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Represents an Address resource.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/addresses"/>
+ */
+@Beta
+public final class Address extends Resource {
+
+   private final String status;
+   private final Optional<URI> user;
+   private final URI region;
+   private final String address;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "status", "user",
+           "region", "address"
+   })
+   private Address(String id, Date creationTimestamp, URI selfLink, String name, String description,
+                   String status, URI user, URI region, String address) {
+      super(Kind.ADDRESS, id, creationTimestamp, selfLink, name, description);
+      this.status = checkNotNull(status, "status of %s", name);
+      this.user = fromNullable(user);
+      this.region = checkNotNull(region, "region of %s", name);
+      this.address = checkNotNull(address, "address of %s", name);
+   }
+
+   /**
+    * @return The status of the address. Valid items are RESERVED and IN USE.
+    *   A reserved address is currently available to the project and can be
+    *   used by a resource. An in-use address is currently being used by a resource.
+    */
+   public String getStatus() {
+      return status;
+   }
+
+   /**
+    * @return URL of the resource currently using this address.
+    */
+   public Optional<URI> getUser() {
+      return user;
+   }
+
+   /**
+    * @return URL of the region where the address resides.
+    */
+   public URI getRegion() {
+      return region;
+   }
+
+   /**
+    * @return The IP address represented by this resource.
+    */
+   public String getAddress() {
+      return address;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Address that = Address.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.region, that.region);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("status", status)
+              .add("user", user.orNull())
+              .add("region", region)
+              .add("address", address);
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromAddress(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+      private String status;
+      private URI user;
+      private URI region;
+      private String address;
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Address#getStatus()
+       */
+      public Builder status(String status) {
+         this.status = status;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Address#getUser()
+       */
+      public Builder user(URI user) {
+         this.user = user;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Address#getRegion()
+       */
+      public Builder region(URI region) {
+         this.region = region;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Address#getAddress()
+       */
+      public Builder address(String address) {
+         this.address = address;
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public Address build() {
+         return new Address(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, status, user, region, address);
+      }
+
+      public Builder fromAddress(Address in) {
+         return super.fromResource(in)
+                 .status(in.getStatus())
+                 .user(in.getUser().orNull())
+                 .region(in.getRegion())
+                 .address(in.getAddress());
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
new file mode 100644
index 0000000..8dc6b76
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.beans.ConstructorProperties;
+import java.net.URI;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Deprecation information for an image or kernel
+ *
+ * @author Andrew Bayer
+ */
+public class Deprecated {
+   private final Optional<String> state;
+   private final Optional<URI> replacement;
+   private final Optional<String> deprecated;
+   private final Optional<String> obsolete;
+   private final Optional<String> deleted;
+
+   @ConstructorProperties({"state", "replacement", "deprecated", "obsolete", "deleted"})
+   public Deprecated(String state, URI replacement, String deprecated, String obsolete,
+                     String deleted) {
+      this.state = fromNullable(state);
+      this.replacement = fromNullable(replacement);
+      this.deprecated = fromNullable(deprecated);
+      this.obsolete = fromNullable(obsolete);
+      this.deleted = fromNullable(deleted);
+   }
+
+   /**
+    * @return The deprecation state of this image.
+    */
+   public Optional<String> getState() {
+      return state;
+   }
+
+   /**
+    * @return A fully-qualified URL of the suggested replacement for the deprecated image.
+    */
+   public Optional<URI> getReplacement() {
+      return replacement;
+   }
+
+   /**
+    * @return An optional RFC3339 timestamp for when the deprecation state of this resource will be changed to DEPRECATED.
+    */
+   public Optional<String> getDeprecated() {
+      return deprecated;
+   }
+
+   /**
+    * @return An optional RFC3339 timestamp on or after which the deprecation state of this resource will be changed toOBSOLETE.
+    */
+   public Optional<String> getObsolete() {
+      return obsolete;
+   }
+
+   /**
+    * @return An optional RFC3339 timestamp on or after which the deprecation state of this resource will be changed to DELETED.
+    */
+   public Optional<String> getDeleted() {
+      return deleted;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(state, replacement, deprecated, obsolete, deleted);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Deprecated that = Deprecated.class.cast(obj);
+      return equal(this.state, that.state)
+              && equal(this.replacement, that.replacement)
+              && equal(this.deprecated, that.deprecated)
+              && equal(this.obsolete, that.obsolete)
+              && equal(this.deleted, that.deleted);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return toStringHelper(this)
+              .omitNullValues()
+              .add("state", state.orNull())
+              .add("replacement", replacement.orNull())
+              .add("deprecated", deprecated.orNull())
+              .add("obsolete", obsolete.orNull())
+              .add("deleted", deleted.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromDeprecated(this);
+   }
+
+   public static class Builder {
+      private String state;
+      private URI replacement;
+      private String deprecated;
+      private String obsolete;
+      private String deleted;
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Deprecated#getState()
+       */
+      public Builder state(String state) {
+         this.state = state;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Deprecated#getReplacement()
+       */
+      public Builder replacement(URI replacement) {
+         this.replacement = replacement;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Deprecated#getDeprecated()
+       */
+      public Builder deprecated(String deprecated) {
+         this.deprecated = deprecated;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Deprecated#getObsolete()
+       */
+      public Builder obsolete(String obsolete) {
+         this.obsolete = obsolete;
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Deprecated#getDeprecated()
+       */
+      public Builder deleted(String deleted) {
+         this.deleted = deleted;
+         return this;
+      }
+
+      public Deprecated build() {
+         return new Deprecated(state, replacement, deprecated, obsolete, deleted);
+      }
+
+      public Builder fromDeprecated(Deprecated in) {
+         return new Builder().state(in.getState().orNull())
+                 .replacement(in.getReplacement().orNull())
+                 .deprecated(in.getDeprecated().orNull())
+                 .obsolete(in.getObsolete().orNull())
+                 .deleted(in.getDeleted().orNull());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
index a34c32f..df5e38c 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
@@ -16,27 +16,26 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
+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 static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
 
 /**
  * A persistent disk resource
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/disks"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/disks"/>
  */
 @Beta
-public final class Disk extends Resource {
+public final class Disk extends AbstractDisk {
 
-   private final Integer sizeGb;
    private final URI zone;
-   private final String status;
 
    @ConstructorProperties({
            "id", "creationTimestamp", "selfLink", "name", "description", "sizeGb", "zone",
@@ -44,17 +43,8 @@ public final class Disk extends Resource {
    })
    private Disk(String id, Date creationTimestamp, URI selfLink, String name, String description,
                 Integer sizeGb, URI zone, String status) {
-      super(Kind.DISK, id, creationTimestamp, selfLink, name, description);
-      this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
+      super(Kind.DISK, id, creationTimestamp, selfLink, name, description, sizeGb, status);
       this.zone = checkNotNull(zone, "zone of %s", name);
-      this.status = checkNotNull(status, "status of %s", name);
-   }
-
-   /**
-    * @return size of the persistent disk, specified in GB.
-    */
-   public int getSizeGb() {
-      return sizeGb;
    }
 
    /**
@@ -65,10 +55,16 @@ public final class Disk extends Resource {
    }
 
    /**
-    * @return the status of disk creation.
+    * {@inheritDoc}
     */
-   public String getStatus() {
-      return status;
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Disk that = Disk.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.zone, that.zone);
    }
 
    /**
@@ -77,9 +73,7 @@ public final class Disk extends Resource {
    protected Objects.ToStringHelper string() {
       return super.string()
               .omitNullValues()
-              .add("sizeGb", sizeGb)
-              .add("zone", zone)
-              .add("status", status);
+              .add("zone", zone);
    }
 
    /**
@@ -98,19 +92,9 @@ public final class Disk extends Resource {
       return new Builder().fromDisk(this);
    }
 
-   public static final class Builder extends Resource.Builder<Builder> {
+   public static final class Builder extends AbstractDisk.Builder<Builder> {
 
-      private Integer sizeGb;
-      private URI zone;;
-      private String status;
-
-      /**
-       * @see Disk#getSizeGb()
-       */
-      public Builder sizeGb(Integer sizeGb) {
-         this.sizeGb = sizeGb;
-         return this;
-      }
+      private URI zone;
 
       /**
        * @see Disk#getZone()
@@ -120,15 +104,6 @@ public final class Disk extends Resource {
          return this;
       }
 
-      /**
-       * @see Disk#getStatus()
-       */
-      public Builder status(String status) {
-         this.status = status;
-         return this;
-      }
-
-
       @Override
       protected Builder self() {
          return this;
@@ -136,14 +111,12 @@ public final class Disk extends Resource {
 
       public Disk build() {
          return new Disk(super.id, super.creationTimestamp, super.selfLink, super.name,
-                 super.description, sizeGb, zone, status);
+                 super.description, super.sizeGb, zone, super.status);
       }
 
       public Builder fromDisk(Disk in) {
-         return super.fromResource(in)
-                 .sizeGb(in.getSizeGb())
-                 .zone(in.getZone())
-                 .status(in.getStatus());
+         return super.fromAbstractDisk(in)
+                 .zone(in.getZone());
       }
 
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
index 141936e..52d51ab 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
@@ -16,17 +16,6 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.RangeSet;
-import com.google.common.collect.TreeRangeSet;
-
-import java.beans.ConstructorProperties;
-import java.net.URI;
-import java.util.Date;
-import java.util.Set;
-
 import static com.google.common.base.Objects.equal;
 import static com.google.common.base.Objects.toStringHelper;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -34,11 +23,22 @@ import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Range.closed;
 import static com.google.common.collect.Range.singleton;
 
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+import java.util.Set;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.RangeSet;
+import com.google.common.collect.TreeRangeSet;
+
 /**
  * Represents a network firewall
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/firewalls"/>
  * @see <a href="https://developers.google.com/compute/docs/networking#firewalls"/>
  */
 @Beta
@@ -83,7 +83,7 @@ public final class Firewall extends Resource {
    }
 
    /**
-    * @return a list of instance tags which this rule applies to. One or both of sourceRanges and sourceTags may be
+    * @return a list of instance items which this rule applies to. One or both of sourceRanges and sourceTags may be
     *         set; an inbound connection is allowed if either the range or the tag of the source matches.
     */
    public Set<String> getSourceTags() {
@@ -93,7 +93,7 @@ public final class Firewall extends Resource {
    /**
     * If no targetTags are specified, the firewall rule applies to all instances on the specified network.
     *
-    * @return a list of instance tags indicating sets of instances located on network which may make network
+    * @return a list of instance items indicating sets of instances located on network which may make network
     *         connections as specified in allowed.
     */
    public Set<String> getTargetTags() {
@@ -241,7 +241,7 @@ public final class Firewall extends Resource {
     * permitted connection.
     *
     * @author David Alves
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/firewalls"/>
     */
    public static final class Rule {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Image.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Image.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Image.java
index d521bbb..8bbfa98 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Image.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Image.java
@@ -16,24 +16,24 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
+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 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 com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
 
 /**
  * Represents a disk image to use on an instance.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/images"/>
  */
 @Beta
 public final class Image extends Resource {
@@ -41,17 +41,19 @@ public final class Image extends Resource {
    private final String sourceType;
    private final Optional<URI> preferredKernel;
    private final RawDisk rawDisk;
+   private final Optional<Deprecated> deprecated;
 
    @ConstructorProperties({
            "id", "creationTimestamp", "selfLink", "name", "description", "sourceType", "preferredKernel",
-           "rawDisk"
+           "rawDisk", "deprecated"
    })
    protected Image(String id, Date creationTimestamp, URI selfLink, String name, String description,
-                   String sourceType, URI preferredKernel, RawDisk rawDisk) {
+                   String sourceType, URI preferredKernel, RawDisk rawDisk, Deprecated deprecated) {
       super(Kind.IMAGE, id, creationTimestamp, selfLink, name, description);
       this.sourceType = checkNotNull(sourceType, "sourceType of %s", name);
       this.preferredKernel = fromNullable(preferredKernel);
-      this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name); ;
+      this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name);
+      this.deprecated = fromNullable(deprecated);
    }
 
    /**
@@ -76,6 +78,13 @@ public final class Image extends Resource {
    }
 
    /**
+    * @return the deprecation information for this image
+    */
+   public Optional<Deprecated> getDeprecated() {
+      return deprecated;
+   }
+
+   /**
     * {@inheritDoc}
     */
    protected Objects.ToStringHelper string() {
@@ -83,7 +92,8 @@ public final class Image extends Resource {
               .omitNullValues()
               .add("sourceType", sourceType)
               .add("preferredKernel", preferredKernel.orNull())
-              .add("rawDisk", rawDisk);
+              .add("rawDisk", rawDisk)
+              .add("deprecated", deprecated.orNull());
    }
 
    /**
@@ -107,6 +117,7 @@ public final class Image extends Resource {
       private String sourceType;
       private URI preferredKernel;
       private RawDisk rawDisk;
+      private Deprecated deprecated;
 
       /**
        * @see Image#getSourceType()
@@ -125,6 +136,14 @@ public final class Image extends Resource {
       }
 
       /**
+       * @see Image#getDeprecated()
+       */
+      public Builder deprecated(Deprecated deprecated) {
+         this.deprecated = checkNotNull(deprecated, "deprecated");
+         return this;
+      }
+
+      /**
        * @see Image#getRawDisk()
        */
       public Builder rawDisk(RawDisk rawDisk) {
@@ -139,14 +158,15 @@ public final class Image extends Resource {
 
       public Image build() {
          return new Image(super.id, super.creationTimestamp, super.selfLink, super.name,
-                 super.description, sourceType, preferredKernel, rawDisk);
+                 super.description, sourceType, preferredKernel, rawDisk, deprecated);
       }
 
       public Builder fromImage(Image in) {
          return super.fromResource(in)
                  .sourceType(in.getSourceType())
                  .preferredKernel(in.getPreferredKernel().orNull())
-                 .rawDisk(in.getRawDisk());
+                 .rawDisk(in.getRawDisk())
+                 .deprecated(in.getDeprecated().orNull());
       }
 
    }
@@ -155,7 +175,7 @@ public final class Image extends Resource {
     * A raw disk image, usually the base for an image.
     *
     * @author David Alves
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/images"/>
     */
    public static class RawDisk {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Instance.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Instance.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Instance.java
index 996d7ec..12b3237 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Instance.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Instance.java
@@ -16,29 +16,28 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-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;
-import org.jclouds.javax.annotation.Nullable;
+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.Map;
 import java.util.Set;
 
-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 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 virtual machine.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances"/>
  */
 @Beta
 public class Instance extends Resource {
@@ -52,7 +51,7 @@ public class Instance extends Resource {
       TERMINATED
    }
 
-   protected final Set<String> tags;
+   protected final Tags tags;
    protected final URI image;
    protected final URI machineType;
    protected final Status status;
@@ -60,15 +59,15 @@ public class Instance extends Resource {
    protected final URI zone;
    protected final Set<NetworkInterface> networkInterfaces;
    protected final Set<AttachedDisk> disks;
-   protected final Map<String, String> metadata;
+   protected final Metadata metadata;
    protected final Set<ServiceAccount> serviceAccounts;
 
    protected Instance(String id, Date creationTimestamp, URI selfLink, String name, String description,
-                      Set<String> tags, URI image, URI machineType, Status status, String statusMessage,
+                      Tags tags, URI image, URI machineType, Status status, String statusMessage,
                       URI zone, Set<NetworkInterface> networkInterfaces, Set<AttachedDisk> disks,
-                      Map<String, String> metadata, Set<ServiceAccount> serviceAccounts) {
+                      Metadata metadata, Set<ServiceAccount> serviceAccounts) {
       super(Kind.INSTANCE, id, creationTimestamp, selfLink, name, description);
-      this.tags = tags == null ? ImmutableSet.<String>of() : tags;
+      this.tags = checkNotNull(tags, "tags");
       this.image = checkNotNull(image, "image");
       this.machineType = checkNotNull(machineType, "machineType of %s", name);
       this.status = checkNotNull(status, "status");
@@ -76,7 +75,7 @@ public class Instance extends Resource {
       this.zone = checkNotNull(zone, "zone of %s", name);
       this.networkInterfaces = networkInterfaces == null ? ImmutableSet.<NetworkInterface>of() : networkInterfaces;
       this.disks = disks == null ? ImmutableSet.<AttachedDisk>of() : disks;
-      this.metadata = metadata == null ? ImmutableMap.<String, String>of() : metadata;
+      this.metadata = checkNotNull(metadata, "metadata");
       this.serviceAccounts = serviceAccounts == null ? ImmutableSet.<ServiceAccount>of() : serviceAccounts;
    }
 
@@ -84,9 +83,9 @@ public class Instance extends Resource {
     * Used to identify valid sources or targets for network firewalls. Provided by the client when the instance is
     * created. Each tag must be unique, must be 1-63 characters long, and comply with RFC1035.
     *
-    * @return an optional set of tags applied to this instance.
+    * @return an optional set of items applied to this instance.
     */
-   public Set<String> getTags() {
+   public Tags getTags() {
       return tags;
    }
 
@@ -147,7 +146,7 @@ public class Instance extends Resource {
    /**
     * @return metadata for this instance
     */
-   public Map<String, String> getMetadata() {
+   public Metadata getMetadata() {
       return metadata;
    }
 
@@ -162,10 +161,23 @@ public class Instance extends Resource {
    /**
     * {@inheritDoc}
     */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Instance that = Instance.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.zone, that.zone);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    protected Objects.ToStringHelper string() {
       return super.string()
               .omitNullValues()
-              .add("tags", tags)
+              .add("items", tags)
               .add("image", image)
               .add("machineType", machineType)
               .add("status", status)
@@ -195,30 +207,23 @@ public class Instance extends Resource {
 
    public static final class Builder extends Resource.Builder<Builder> {
 
-      private ImmutableSet.Builder<String> tags = ImmutableSet.builder();
+      private Tags tags;
       private URI image;
       private URI machineType;
       private Status status;
       private String statusMessage;
       private URI zone;
+      private Metadata metadata;
       private ImmutableSet.Builder<NetworkInterface> networkInterfaces = ImmutableSet.builder();
       private ImmutableSet.Builder<AttachedDisk> disks = ImmutableSet.builder();
-      private ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder();
       private ImmutableSet.Builder<ServiceAccount> serviceAccounts = ImmutableSet.builder();
 
-      /**
-       * @see Instance#getTags()
-       */
-      public Builder addTag(String tag) {
-         this.tags.add(tag);
-         return this;
-      }
 
       /**
        * @see Instance#getTags()
        */
-      public Builder tags(Set<String> tags) {
-         this.tags.addAll(tags);
+      public Builder tags(Tags tags) {
+         this.tags = tags;
          return this;
       }
 
@@ -297,16 +302,8 @@ public class Instance extends Resource {
       /**
        * @see Instance#getMetadata()
        */
-      public Builder metadata(Map<String, String> metadata) {
-         this.metadata = new ImmutableMap.Builder<String, String>().putAll(metadata);
-         return this;
-      }
-
-      /**
-       * @see Instance#getMetadata()
-       */
-      public Builder addMetadata(String key, String value) {
-         this.metadata.put(checkNotNull(key, "key"), checkNotNull(value, "value of %s", key));
+      public Builder metadata(Metadata metadata) {
+         this.metadata = metadata;
          return this;
       }
 
@@ -321,7 +318,7 @@ public class Instance extends Resource {
       /**
        * @see Instance#getServiceAccounts()
        */
-      public Builder serviceAccoutns(Set<ServiceAccount> serviceAccounts) {
+      public Builder serviceAccounts(Set<ServiceAccount> serviceAccounts) {
          this.serviceAccounts.addAll(serviceAccounts);
          return this;
       }
@@ -334,8 +331,8 @@ public class Instance extends Resource {
 
       public Instance build() {
          return new Instance(super.id, super.creationTimestamp, super.selfLink, super.name,
-                 super.description, tags.build(), image, machineType, status, statusMessage, zone,
-                 networkInterfaces.build(), disks.build(), metadata.build(), serviceAccounts.build());
+                 super.description, tags, image, machineType, status, statusMessage, zone,
+                 networkInterfaces.build(), disks.build(), metadata, serviceAccounts.build());
       }
 
       public Builder fromInstance(Instance in) {
@@ -349,14 +346,130 @@ public class Instance extends Resource {
                  .networkInterfaces(in.getNetworkInterfaces())
                  .disks(in.getDisks())
                  .metadata(in.getMetadata())
-                 .serviceAccoutns(in.getServiceAccounts());
+                 .serviceAccounts(in.getServiceAccounts());
+      }
+   }
+
+
+
+
+   /**
+    * Tags for an instance, with their fingerprint.
+    */
+   public static class Tags {
+      private final String fingerprint;
+      private final Set<String> items;
+
+      @ConstructorProperties({"fingerprint", "items"})
+      public Tags(String fingerprint, @Nullable Set<String> items) {
+         this.fingerprint = checkNotNull(fingerprint);
+         this.items = items == null ? ImmutableSet.<String>of() : items;
+      }
+
+      /**
+       * Used to identify valid sources or targets for network firewalls. Provided by the client when the instance is
+       * created. Each tag must be unique, must be 1-63 characters long, and comply with RFC1035.
+       *
+       * @return an optional set of items applied to this instance.
+       */
+      public Set<String> getItems() {
+         return items;
+      }
+
+      /**
+       * Gets the fingerprint for the items - needed for updating them.
+       *
+       * @return the fingerprint string for the items.
+       */
+      public String getFingerprint() {
+         return fingerprint;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(fingerprint, items);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         Tags that = Tags.class.cast(obj);
+         return equal(this.items, that.items)
+                 && equal(this.fingerprint, that.fingerprint);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      protected Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .add("items", items)
+                 .add("fingerprint", fingerprint);
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static final class Builder {
+
+         private ImmutableSet.Builder<String> items = ImmutableSet.builder();
+         private String fingerprint;
+
+         /**
+          * @see Tags#getItems()
+          */
+         public Builder addItem(String item) {
+            this.items.add(item);
+            return this;
+         }
+
+         /**
+          * @see Tags#getItems()
+          */
+         public Builder items(Set<String> items) {
+            this.items.addAll(items);
+            return this;
+         }
+
+         /**
+          * @see org.jclouds.googlecomputeengine.domain.Instance.Tags#getFingerprint()
+          */
+         public Builder fingerprint(String fingerprint) {
+            this.fingerprint = fingerprint;
+            return this;
+         }
+
+         public Tags build() {
+            return new Tags(this.fingerprint, this.items.build());
+         }
+
+         public Builder fromTags(Tags in) {
+            return this.fingerprint(in.getFingerprint())
+                    .items(in.getItems());
+         }
       }
    }
 
    /**
     * A disk attached to an Instance.
     *
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances"/>
     */
    public static class AttachedDisk {
 
@@ -419,10 +532,9 @@ public class Instance extends Resource {
    }
 
    public static class PersistentAttachedDisk extends AttachedDisk {
-
       public enum Mode {
          READ_WRITE,
-         READ_ONLY
+         READ_ONLY;
       }
 
       @ConstructorProperties({"mode", "source", "deviceName", "index", "deleteOnTerminate"})
@@ -546,7 +658,7 @@ public class Instance extends Resource {
    /**
     * A network interface for an Instance.
     *
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances"/>
     */
    public static final class NetworkInterface {
 
@@ -840,7 +952,7 @@ public class Instance extends Resource {
     * The output of an instance's serial port;
     *
     * @author David Alves
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances/serialPort"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances/serialPort"/>
     */
    public static final class SerialPortOutput {
 
@@ -948,7 +1060,7 @@ public class Instance extends Resource {
     * A service account for which access tokens are to be made available to the instance through metadata queries.
     *
     * @author David Alves
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances"/>
     */
    public static final class ServiceAccount {
 


[05/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiExpectTest.java
index 6429275..4627f9a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiExpectTest.java
@@ -16,6 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseDiskListTest;
 import org.jclouds.googlecomputeengine.parse.ParseDiskTest;
@@ -24,15 +32,6 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertNull;
-
 /**
  * @author David Alves
  */
@@ -43,7 +42,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       HttpRequest get = HttpRequest
               .builder()
               .method("GET")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -53,7 +52,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, get, operationResponse).getDiskApiForProject("myproject");
 
-      assertEquals(api.get("testimage1"),
+      assertEquals(api.getInZone("us-central1-a", "testimage1"),
               new ParseDiskTest().expected());
    }
 
@@ -61,7 +60,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       HttpRequest get = HttpRequest
               .builder()
               .method("GET")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -70,29 +69,68 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, get, operationResponse).getDiskApiForProject("myproject");
 
-      assertNull(api.get("testimage1"));
+      assertNull(api.getInZone("us-central1-a", "testimage1"));
    }
 
    public void testInsertDiskResponseIs2xx() {
       HttpRequest insert = HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(payloadFromResourceWithContentType("/disk_insert.json", MediaType.APPLICATION_JSON))
               .build();
 
       HttpResponse insertDiskResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation.json")).build();
+              .payload(payloadFromResource("/zone_operation.json")).build();
 
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, insert,
               insertDiskResponse).getDiskApiForProject("myproject");
 
-      assertEquals(api.createInZone("testimage1", 1, URI.create("https://www.googleapis" +
-              ".com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
-              , new ParseOperationTest().expected());
+      assertEquals(api.createInZone("testimage1", 1, "us-central1-a"), new ParseOperationTest().expected());
+   }
+
+   public void testCreateSnapshotResponseIs2xx() {
+      HttpRequest createSnapshotRequest = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks"
+                      + "/testimage1/createSnapshot")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/disk_create_snapshot.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse createSnapshotResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation.json")).build();
+
+      DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, createSnapshotRequest,
+              createSnapshotResponse).getDiskApiForProject("myproject");
+
+      assertEquals(api.createSnapshotInZone("us-central1-a", "testimage1", "test-snap"), new ParseOperationTest().expected());
+   }
+
+   public void testCreateSnapshotResponseIs4xx() {
+      HttpRequest createSnapshotRequest = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks"
+                      + "/testimage1/createSnapshot")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/disk_create_snapshot.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse createSnapshotResponse = HttpResponse.builder().statusCode(404).build();
+
+      DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, createSnapshotRequest,
+              createSnapshotResponse).getDiskApiForProject("myproject");
+
+      assertNull(api.createSnapshotInZone("us-central1-a", "testimage1", "test-snap"));
    }
 
    public void testDeleteDiskResponseIs2xx() {
@@ -100,17 +138,17 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/disks/testimage1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
       HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation.json")).build();
+              .payload(payloadFromResource("/zone_operation.json")).build();
 
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, delete, deleteResponse).getDiskApiForProject("myproject");
 
-      assertEquals(api.delete("testimage1"),
+      assertEquals(api.deleteInZone("us-central1-a", "testimage1"),
               new ParseOperationTest().expected());
    }
 
@@ -119,7 +157,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/disks/testimage1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -128,7 +166,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, delete, deleteResponse).getDiskApiForProject("myproject");
 
-      assertNull(api.delete("testimage1"));
+      assertNull(api.deleteInZone("us-central1-a", "testimage1"));
    }
 
    public void testListDisksResponseIs2xx() {
@@ -136,7 +174,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/disks")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -146,7 +184,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, list, operationResponse).getDiskApiForProject("myproject");
 
-      assertEquals(api.listFirstPage().toString(),
+      assertEquals(api.listFirstPageInZone("us-central1-a").toString(),
               new ParseDiskListTest().expected().toString());
    }
 
@@ -155,7 +193,7 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/disks")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -164,6 +202,6 @@ public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, list, operationResponse).getDiskApiForProject("myproject");
 
-      assertTrue(api.list().concat().isEmpty());
+      assertTrue(api.listInZone("us-central1-a").concat().isEmpty());
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiLiveTest.java
index 2b42cd7..86aefb1 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/DiskApiLiveTest.java
@@ -19,7 +19,6 @@ package org.jclouds.googlecomputeengine.features;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
-import java.net.URI;
 import java.util.List;
 
 import org.jclouds.collect.PagedIterable;
@@ -37,11 +36,9 @@ import com.google.common.collect.Lists;
  */
 public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
-   private static final String DISK_NAME = "disk-api-live-test-disk";
-   private static final int TIME_WAIT = 10;
-
-   private URI zoneUrl;
-   private int sizeGb = 1;
+   public static final String DISK_NAME = "disk-api-live-test-disk";
+   public static final int TIME_WAIT = 30;
+   public static final int sizeGb = 1;
 
    private DiskApi api() {
       return api.getDiskApiForProject(userProject.get());
@@ -50,15 +47,14 @@ public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live")
    public void testInsertDisk() {
       Project project = api.getProjectApi().get(userProject.get());
-      zoneUrl = getDefaultZoneUrl(project.getName());
-      assertOperationDoneSucessfully(api().createInZone(DISK_NAME, sizeGb, zoneUrl), TIME_WAIT);
+      assertZoneOperationDoneSucessfully(api().createInZone(DISK_NAME, sizeGb, DEFAULT_ZONE_NAME), TIME_WAIT);
 
    }
 
    @Test(groups = "live", dependsOnMethods = "testInsertDisk")
    public void testGetDisk() {
 
-      Disk disk = api().get(DISK_NAME);
+      Disk disk = api().getInZone(DEFAULT_ZONE_NAME, DISK_NAME);
       assertNotNull(disk);
       assertDiskEquals(disk);
    }
@@ -66,7 +62,7 @@ public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live", dependsOnMethods = "testGetDisk")
    public void testListDisk() {
 
-      PagedIterable<Disk> disks = api().list(new ListOptions.Builder()
+      PagedIterable<Disk> disks = api().listInZone(DEFAULT_ZONE_NAME, new ListOptions.Builder()
               .filter("name eq " + DISK_NAME));
 
       List<Disk> disksAsList = Lists.newArrayList(disks.concat());
@@ -80,13 +76,13 @@ public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live", dependsOnMethods = "testListDisk")
    public void testDeleteDisk() {
 
-      assertOperationDoneSucessfully(api().delete(DISK_NAME), TIME_WAIT);
+      assertZoneOperationDoneSucessfully(api().deleteInZone(DEFAULT_ZONE_NAME, DISK_NAME), TIME_WAIT);
    }
 
    private void assertDiskEquals(Disk result) {
       assertEquals(result.getName(), DISK_NAME);
       assertEquals(result.getSizeGb(), sizeGb);
-      assertEquals(result.getZone(), zoneUrl);
+      assertEquals(result.getZone(), getDefaultZoneUrl(userProject.get()));
    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiExpectTest.java
index 5dc6fdf..6345c51 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiExpectTest.java
@@ -16,24 +16,6 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.googlecomputeengine.domain.Firewall;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
-import org.jclouds.googlecomputeengine.options.FirewallOptions;
-import org.jclouds.googlecomputeengine.parse.ParseFirewallListTest;
-import org.jclouds.googlecomputeengine.parse.ParseFirewallTest;
-import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.io.Payload;
-import org.testng.annotations.Test;
-
-import javax.ws.rs.core.MediaType;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Set;
-
 import static com.google.common.base.Joiner.on;
 import static com.google.common.collect.Iterables.transform;
 import static java.lang.String.format;
@@ -46,6 +28,26 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static org.testng.AssertJUnit.assertNull;
 
+import java.io.IOException;
+import java.net.URI;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.FirewallOptions;
+import org.jclouds.googlecomputeengine.parse.ParseFirewallListTest;
+import org.jclouds.googlecomputeengine.parse.ParseFirewallTest;
+import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.io.Payload;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+
 /**
  * @author David Alves
  */
@@ -56,7 +58,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
            .builder()
            .method("GET")
            .endpoint("https://www.googleapis" +
-                   ".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
+                   ".com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -106,7 +108,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -123,7 +125,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       HttpRequest request = HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(firewallPayloadFirewallOfName(
@@ -142,7 +144,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               TOKEN_RESPONSE, request, insertFirewallResponse).getFirewallApiForProject("myproject");
 
       assertEquals(api.createInNetwork("myfw", URI.create("https://www.googleapis" +
-              ".com/compute/v1beta13/projects/myproject/networks/default"),
+              ".com/compute/v1beta15/projects/myproject/global/networks/default"),
               new FirewallOptions()
                       .addAllowedRule(Firewall.Rule.builder()
                               .IPProtocol(IPProtocol.TCP)
@@ -158,7 +160,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       HttpRequest update = HttpRequest
               .builder()
               .method("PUT")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/myfw")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(firewallPayloadFirewallOfName(
@@ -181,7 +183,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               new FirewallOptions()
                       .name("myfw")
                       .network(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/networks/default"))
+                              ".com/compute/v1beta15/projects/myproject/global/networks/default"))
                       .addAllowedRule(Firewall.Rule.builder()
                               .IPProtocol(IPProtocol.TCP)
                               .addPort(22)
@@ -195,7 +197,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       HttpRequest update = HttpRequest
               .builder()
               .method("PATCH")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/myfw")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(firewallPayloadFirewallOfName(
@@ -218,7 +220,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               new FirewallOptions()
                       .name("myfw")
                       .network(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/networks/default"))
+                              ".com/compute/v1beta15/projects/myproject/global/networks/default"))
                       .addAllowedRule(Firewall.Rule.builder()
                               .IPProtocol(IPProtocol.TCP)
                               .addPort(22)
@@ -233,7 +235,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls/default-allow-internal")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls/default-allow-internal")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -252,7 +254,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls/default-allow-internal")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls/default-allow-internal")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -269,7 +271,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -288,7 +290,7 @@ public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiLiveTest.java
index 72c903f..8c550b7 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/FirewallApiLiveTest.java
@@ -16,8 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.Firewall;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
@@ -25,12 +30,8 @@ import org.jclouds.googlecomputeengine.options.FirewallOptions;
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
-import java.util.List;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
 
 /**
  * @author David Alves
@@ -50,7 +51,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    public void testInsertFirewall() {
 
       // need to create the network first
-      assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
               (FIREWALL_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
 
       FirewallOptions firewall = new FirewallOptions()
@@ -62,7 +63,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
               .addSourceTag("tag1")
               .addTargetTag("tag2");
 
-      assertOperationDoneSucessfully(api().createInNetwork(FIREWALL_NAME, getNetworkUrl(userProject.get(),
+      assertGlobalOperationDoneSucessfully(api().createInNetwork(FIREWALL_NAME, getNetworkUrl(userProject.get(),
               FIREWALL_NETWORK_NAME), firewall), TIME_WAIT);
 
    }
@@ -72,7 +73,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
       FirewallOptions firewall = new FirewallOptions()
               .name(FIREWALL_NAME)
-              .network(getNetworkUrl(userProject.get(),FIREWALL_NETWORK_NAME))
+              .network(getNetworkUrl(userProject.get(), FIREWALL_NETWORK_NAME))
               .addSourceRange("10.0.0.0/8")
               .addSourceTag("tag1")
               .addTargetTag("tag2")
@@ -83,7 +84,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
                               .build()));
 
 
-      assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
 
    }
 
@@ -92,7 +93,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
       FirewallOptions firewall = new FirewallOptions()
               .name(FIREWALL_NAME)
-              .network(getNetworkUrl(userProject.get(),FIREWALL_NETWORK_NAME))
+              .network(getNetworkUrl(userProject.get(), FIREWALL_NETWORK_NAME))
               .allowedRules(ImmutableSet.of(
                       Firewall.Rule.builder()
                               .IPProtocol(IPProtocol.TCP)
@@ -106,7 +107,7 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
               .addSourceTag("tag1")
               .addTargetTag("tag2");
 
-      assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
 
    }
 
@@ -149,8 +150,8 @@ public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live", dependsOnMethods = "testListFirewall")
    public void testDeleteFirewall() {
 
-      assertOperationDoneSucessfully(api().delete(FIREWALL_NAME), TIME_WAIT);
-      assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
+      assertGlobalOperationDoneSucessfully(api().delete(FIREWALL_NAME), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
               (FIREWALL_NETWORK_NAME), TIME_WAIT);
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiExpectTest.java
new file mode 100644
index 0000000..412dc32
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiExpectTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.googlecomputeengine.parse.ParseOperationListTest;
+import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class GlobalOperationApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
+           ".com/compute/v1beta15/projects/myproject/global/operations";
+
+   public static final HttpRequest GET_GLOBAL_OPERATION_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse GET_GLOBAL_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/global_operation.json")).build();
+
+   public void testGetOperationResponseIs2xx() throws Exception {
+
+      GlobalOperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_GLOBAL_OPERATION_REQUEST, GET_GLOBAL_OPERATION_RESPONSE).getGlobalOperationApiForProject("myproject");
+
+      assertEquals(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testGetOperationResponseIs4xx() throws Exception {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_GLOBAL_OPERATION_REQUEST, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      assertNull(globalOperationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"));
+   }
+
+   public void testDeleteOperationResponseIs2xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(204).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      globalOperationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testDeleteOperationResponseIs4xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      globalOperationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testLisOperationWithNoOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/global_operation_list.json")).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      assertEquals(globalOperationApi.listFirstPage().toString(),
+              new ParseOperationListTest().expected().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX +
+                      "?pageToken=CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcG" +
+                      "VyYXRpb24tMTM1MjI0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz&" +
+                      "filter=" +
+                      "status%20eq%20done&" +
+                      "maxResults=3")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/global_operation_list.json")).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      assertEquals(globalOperationApi.listAtMarker("CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcGVyYXRpb24tMTM1Mj" +
+              "I0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz",
+              new ListOptions.Builder().filter("status eq done").maxResults(3)).toString(),
+              new ParseOperationListTest().expected().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs4xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      GlobalOperationApi globalOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getGlobalOperationApiForProject("myproject");
+
+      assertTrue(globalOperationApi.list().concat().isEmpty());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiLiveTest.java
new file mode 100644
index 0000000..42adbe6
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/GlobalOperationApiLiveTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.features.ProjectApiLiveTest.addItemToMetadata;
+import static org.jclouds.googlecomputeengine.features.ProjectApiLiveTest.deleteItemFromMetadata;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author David Alves
+ */
+public class GlobalOperationApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String METADATA_ITEM_KEY = "operationLiveTestTestProp";
+   private static final String METADATA_ITEM_VALUE = "operationLiveTestTestValue";
+   private Operation addOperation;
+   private Operation deleteOperation;
+
+   private GlobalOperationApi api() {
+      return api.getGlobalOperationApiForProject(userProject.get());
+   }
+
+
+   @Test(groups = "live")
+   public void testCreateOperations() {
+      //create some operations by adding and deleting metadata items
+      // this will make sure there is stuff to listFirstPage
+      addOperation = assertGlobalOperationDoneSucessfully(addItemToMetadata(api.getProjectApi(),
+              userProject.get(), METADATA_ITEM_KEY, METADATA_ITEM_VALUE), 20);
+      deleteOperation = assertGlobalOperationDoneSucessfully(deleteItemFromMetadata(api
+              .getProjectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
+
+      assertNotNull(addOperation);
+      assertNotNull(deleteOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testGetOperation() {
+      Operation operation = api().get(addOperation.getName());
+      assertNotNull(operation);
+      assertOperationEquals(operation, this.addOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testListOperationsWithFiltersAndPagination() {
+      PagedIterable<Operation> operations = api().list(new ListOptions.Builder()
+              .filter("operationType eq setMetadata")
+              .maxResults(1));
+
+      // make sure that in spite of having only one result per page we get at least two results
+      final AtomicInteger counter = new AtomicInteger();
+      operations.firstMatch(new Predicate<IterableWithMarker<Operation>>() {
+
+         @Override
+         public boolean apply(IterableWithMarker<Operation> input) {
+            counter.addAndGet(Iterables.size(input));
+            return counter.get() == 2;
+         }
+      });
+   }
+
+   private void assertOperationEquals(Operation result, Operation expected) {
+      assertEquals(result.getName(), expected.getName());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiExpectTest.java
index fe7e41f..d8baecf 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiExpectTest.java
@@ -16,6 +16,12 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseImageListTest;
 import org.jclouds.googlecomputeengine.parse.ParseImageTest;
@@ -24,12 +30,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.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertNull;
-
 /**
  * @author David Alves
  */
@@ -40,19 +40,30 @@ public class ImageApiExpectTest 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();
 
    public static final HttpResponse LIST_PROJECT_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
            .payload(staticPayloadFromResource("/image_list.json")).build();
 
+   public static final HttpRequest LIST_GOOGLE_IMAGES_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/google/global/images")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse LIST_GOOGLE_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/image_list_single_page.json")).build();
+
+
    public void testGetImageResponseIs2xx() throws Exception {
       HttpRequest get = HttpRequest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326")
+                      ".com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -71,7 +82,7 @@ public class ImageApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326")
+                      ".com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -88,7 +99,7 @@ public class ImageApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326")
+                      ".com/compute/v1beta15/projects/myproject/global/images/centos-6-2-v20120326")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -107,7 +118,7 @@ public class ImageApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326")
+                      ".com/compute/v1beta15/projects/myproject/global/images/centos-6-2-v20120326")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiLiveTest.java
index f26b8bb..1180949 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ImageApiLiveTest.java
@@ -16,8 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.Image;
@@ -25,17 +31,10 @@ import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTe
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
-import java.util.Iterator;
-import java.util.List;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 /**
- * TODO figure out how to test insert and delete as this requires an image .tar.gz to be present in GCS
- *
  * @author David Alves
  */
 public class ImageApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiExpectTest.java
index 05a2034..1fdf20b 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiExpectTest.java
@@ -16,9 +16,25 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static java.net.URI.create;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+import static org.jclouds.googlecomputeengine.features.ProjectApiExpectTest.GET_PROJECT_REQUEST;
+import static org.jclouds.googlecomputeengine.features.ProjectApiExpectTest.GET_PROJECT_RESPONSE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.domain.Instance;
 import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions.DiskMode;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions.DiskType;
 import org.jclouds.googlecomputeengine.parse.ParseInstanceListTest;
 import org.jclouds.googlecomputeengine.parse.ParseInstanceSerialOutputTest;
 import org.jclouds.googlecomputeengine.parse.ParseInstanceTest;
@@ -27,15 +43,7 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
-import static java.net.URI.create;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertNull;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * @author David Alves
@@ -47,7 +55,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
            .builder()
            .method("GET")
            .endpoint("https://www.googleapis" +
-                   ".com/compute/v1beta13/projects/myproject/instances/test-1")
+                   ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -59,15 +67,26 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
            .builder()
            .method("GET")
            .endpoint("https://www.googleapis" +
-                   ".com/compute/v1beta13/projects/myproject/instances")
+                   ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
    public static final HttpResponse LIST_INSTANCES_RESPONSE = HttpResponse.builder().statusCode(200)
            .payload(staticPayloadFromResource("/instance_list.json")).build();
 
+   public static final HttpRequest LIST_CENTRAL1B_INSTANCES_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint("https://www.googleapis" +
+                   ".com/compute/v1beta15/projects/myproject/zones/us-central1-b/instances")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse LIST_CENTRAL1B_INSTANCES_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/instance_list_central1b_empty.json")).build();
+
    public static final HttpResponse CREATE_INSTANCE_RESPONSE = HttpResponse.builder().statusCode(200)
-           .payload(staticPayloadFromResource("/operation.json")).build();
+           .payload(staticPayloadFromResource("/zone_operation.json")).build();
 
 
    public void testGetInstanceResponseIs2xx() throws Exception {
@@ -76,7 +95,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
               GET_INSTANCE_REQUEST, GET_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
 
-      assertEquals(api.get("test-1"), new ParseInstanceTest().expected());
+      assertEquals(api.getInZone("us-central1-a", "test-1"), new ParseInstanceTest().expected());
    }
 
    public void testGetInstanceResponseIs4xx() throws Exception {
@@ -86,7 +105,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, GET_INSTANCE_REQUEST, operationResponse).getInstanceApiForProject("myproject");
 
-      assertNull(api.get("test-1"));
+      assertNull(api.getInZone("us-central1-a", "test-1"));
    }
 
    public void testGetInstanceSerialPortOutput() throws Exception {
@@ -94,7 +113,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/test-1/serialPort")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/serialPort")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -105,59 +124,63 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, get, operationResponse).getInstanceApiForProject("myproject");
 
-      assertEquals(api.getSerialPortOutput("test-1"), new ParseInstanceSerialOutputTest().expected());
+      assertEquals(api.getSerialPortOutputInZone("us-central1-a", "test-1"), new ParseInstanceSerialOutputTest().expected());
    }
 
    public void testInsertInstanceResponseIs2xxNoOptions() {
       HttpRequest insert = HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(payloadFromResourceWithContentType("/instance_insert_simple.json", MediaType.APPLICATION_JSON))
               .build();
 
-      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+      InstanceApi api = requestsSendResponses(ImmutableMap.of(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_PROJECT_REQUEST, GET_PROJECT_RESPONSE,
+              requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, insert,
-              CREATE_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
+              CREATE_INSTANCE_RESPONSE)).getInstanceApiForProject("myproject");
 
-      InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
+      InstanceTemplate options = InstanceTemplate.builder().forMachineType("us-central1-a/n1-standard-1")
+              .image(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106"))
               .addNetworkInterface(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/default"));
+                      ".com/compute/v1beta15/projects/myproject/global/networks/default"));
 
-      assertEquals(api.createInZone("test-1", options, "us-central1-a"), new ParseOperationTest().expected());
+      assertEquals(api.createInZone("test-1", "us-central1-a", options), new ParseOperationTest().expected());
    }
 
    public void testInsertInstanceResponseIs2xxAllOptions() {
       HttpRequest insert = HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(payloadFromResourceWithContentType("/instance_insert.json", MediaType.APPLICATION_JSON))
               .build();
 
       HttpResponse insertInstanceResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation.json")).build();
+              .payload(payloadFromResource("/zone_operation.json")).build();
 
-      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
-              TOKEN_RESPONSE, insert, insertInstanceResponse).getInstanceApiForProject("myproject");
+      InstanceApi api = requestsSendResponses(ImmutableMap.of(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_PROJECT_REQUEST, GET_PROJECT_RESPONSE,
+              requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, insert, insertInstanceResponse)).getInstanceApiForProject("myproject");
 
-      InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
+      InstanceTemplate options = InstanceTemplate.builder().forMachineType("us-central1-a/n1-standard-1")
               .addNetworkInterface(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/default"), Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
+                      ".com/compute/v1beta15/projects/myproject/global/networks/default"), Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
               .description("desc")
               .image(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106"))
+                      ".com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106"))
               .addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE,
-                      create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test"))
-              .addTag("aTag")
+                      create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/test"))
               .addServiceAccount(Instance.ServiceAccount.builder().email("default").addScopes("myscope").build())
               .addMetadata("aKey", "aValue");
 
-      assertEquals(api.createInZone("test-0", options, "us-central1-a"),
+      assertEquals(api.createInZone("test-0", "us-central1-a", options),
               new ParseOperationTest().expected());
    }
 
@@ -166,17 +189,17 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/test-1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
       HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation.json")).build();
+              .payload(payloadFromResource("/zone_operation.json")).build();
 
       InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
 
-      assertEquals(api.delete("test-1"),
+      assertEquals(api.deleteInZone("us-central1-a", "test-1"),
               new ParseOperationTest().expected());
    }
 
@@ -185,7 +208,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/test-1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -194,7 +217,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
               TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
 
-      assertNull(api.delete("test-1"));
+      assertNull(api.deleteInZone("us-central1-a", "test-1"));
    }
 
    public void testListInstancesResponseIs2xx() {
@@ -203,7 +226,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
               LIST_INSTANCES_REQUEST, LIST_INSTANCES_RESPONSE).getInstanceApiForProject("myproject");
 
-      assertEquals(api.listFirstPage().toString(),
+      assertEquals(api.listFirstPageInZone("us-central1-a").toString(),
               new ParseInstanceListTest().expected().toString());
    }
 
@@ -212,7 +235,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -221,7 +244,172 @@ public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest
       InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, list, operationResponse).getInstanceApiForProject("myproject");
 
-      assertTrue(api.list().concat().isEmpty());
+      assertTrue(api.listInZone("us-central1-a").concat().isEmpty());
+   }
+
+   public void testSetInstanceMetadataResponseIs2xx() {
+      HttpRequest setMetadata = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/setMetadata")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/instance_set_metadata.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation.json")).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, setMetadata, setMetadataResponse).getInstanceApiForProject("myproject");
+
+      assertEquals(api.setMetadataInZone("us-central1-a", "test-1", ImmutableMap.of("foo", "bar"), "efgh"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testSetInstanceMetadataResponseIs4xx() {
+      HttpRequest setMetadata = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/setMetadata")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/instance_set_metadata.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(404).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, setMetadata, setMetadataResponse).getInstanceApiForProject("myproject");
+
+      assertNull(api.setMetadataInZone("us-central1-a", "test-1", ImmutableMap.of("foo", "bar"), "efgh"));
+   }
+
+   public void testResetInstanceResponseIs2xx() {
+      HttpRequest reset = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/reset")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse resetResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation.json")).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, reset, resetResponse).getInstanceApiForProject("myproject");
+
+      assertEquals(api.resetInZone("us-central1-a", "test-1"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testResetInstanceResponseIs4xx() {
+      HttpRequest reset = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/reset")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse resetResponse = HttpResponse.builder().statusCode(404).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, reset, resetResponse).getInstanceApiForProject("myproject");
+
+      assertNull(api.resetInZone("us-central1-a", "test-1"));
+   }
+
+   public void testAttachDiskResponseIs2xx() {
+      HttpRequest attach = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/attachDisk")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/instance_attach_disk.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse attachResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation.json")).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, attach, attachResponse).getInstanceApiForProject("myproject");
+
+      assertEquals(api.attachDiskInZone("us-central1-a", "test-1",
+              new AttachDiskOptions()
+                      .mode(DiskMode.READ_ONLY)
+                      .source(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
+                      .type(DiskType.PERSISTENT)),
+              new ParseOperationTest().expected());
+   }
+
+   public void testAttachDiskResponseIs4xx() {
+      HttpRequest attach = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/attachDisk")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/instance_attach_disk.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse attachResponse = HttpResponse.builder().statusCode(404).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, attach, attachResponse).getInstanceApiForProject("myproject");
+
+      assertNull(api.attachDiskInZone("us-central1-a", "test-1",
+              new AttachDiskOptions()
+                      .mode(DiskMode.READ_ONLY)
+                      .source(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
+                      .type(DiskType.PERSISTENT)));
+
+   }
+
+   public void testDetachDiskResponseIs2xx() {
+      HttpRequest detach = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/detachDisk" +
+                      "?deviceName=test-disk-1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .build();
+
+      HttpResponse detachResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation.json")).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, detach, detachResponse).getInstanceApiForProject("myproject");
+
+      assertEquals(api.detachDiskInZone("us-central1-a", "test-1", "test-disk-1"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testDetachDiskResponseIs4xx() {
+      HttpRequest detach = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/detachDisk" +
+                      "?deviceName=test-disk-1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .build();
+
+      HttpResponse detachResponse = HttpResponse.builder().statusCode(404).build();
+
+      InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, detach, detachResponse).getInstanceApiForProject("myproject");
+
+      assertNull(api.detachDiskInZone("us-central1-a", "test-1", "test-disk-1"));
    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiLiveTest.java
index e4ea6f7..8be4a54 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/InstanceApiLiveTest.java
@@ -18,18 +18,28 @@ package org.jclouds.googlecomputeengine.features;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
+import java.net.URI;
 import java.util.List;
 import java.util.Properties;
 
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.Image;
 import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
+import org.jclouds.googlecomputeengine.domain.Instance.PersistentAttachedDisk;
 import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions.DiskMode;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions.DiskType;
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.inject.Module;
@@ -43,22 +53,44 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    private static final String INSTANCE_NAME = "instance-api-live-test-instance";
    private static final String DISK_NAME = "instance-live-test-disk";
    private static final String IPV4_RANGE = "10.0.0.0/8";
+   private static final String METADATA_ITEM_KEY = "instanceLiveTestTestProp";
+   private static final String METADATA_ITEM_VALUE = "instanceLiveTestTestValue";
+   private static final String ATTACH_DISK_NAME = "instance-api-live-test-attach-disk";
+   private static final String ATTACH_DISK_DEVICE_NAME = "attach-disk-1";
+
    private static final int TIME_WAIT = 600;
 
    private InstanceTemplate instance;
-   
+
    @Override
    protected GoogleComputeEngineApi create(Properties props, Iterable<Module> modules) {
       GoogleComputeEngineApi api = super.create(props, modules);
+      URI imageUri = api.getImageApiForProject("google")
+              .list(new ListOptions.Builder().filter("name eq gcel.*"))
+              .concat()
+              .filter(new Predicate<Image>() {
+                 @Override
+                 public boolean apply(Image input) {
+                    // filter out only images with deprecation state other than "DEPRECATED"
+                    if (input.getDeprecated().isPresent() && input.getDeprecated().get().getState().isPresent()) {
+                       return input.getDeprecated().get().getState().get().equals("DEPRECATED");
+                    }
+                    return true;
+
+                 }
+              })
+              .first()
+              .get()
+              .getSelfLink();
       instance = InstanceTemplate.builder()
-            .forMachineType(getDefaultMachineTypekUrl(userProject.get()))
-            .addNetworkInterface(getNetworkUrl(userProject.get(), INSTANCE_NETWORK_NAME),
-                    Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
-            .addMetadata("mykey", "myvalue")
-            .addTag("atag")
-            .description("a description")
-            .addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE, getDiskUrl(userProject.get(), DISK_NAME))
-            .zone(getDefaultZoneUrl(userProject.get()));
+              .forMachineType(getDefaultMachineTypeUrl(userProject.get()))
+              .addNetworkInterface(getNetworkUrl(userProject.get(), INSTANCE_NETWORK_NAME),
+                      Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
+              .addMetadata("mykey", "myvalue")
+              .description("a description")
+              .addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE, getDiskUrl(userProject.get(), DISK_NAME))
+              .image(imageUri);
+
       return api;
    }
 
@@ -66,32 +98,91 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
       return api.getInstanceApiForProject(userProject.get());
    }
 
+   private DiskApi diskApi() {
+      return api.getDiskApiForProject(userProject.get());
+   }
+
    @Test(groups = "live")
    public void testInsertInstance() {
 
       // need to create the network first
-      assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
               (INSTANCE_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
 
-      assertOperationDoneSucessfully(api.getDiskApiForProject(userProject.get()).createInZone
-              ("instance-live-test-disk", 1, getDefaultZoneUrl(userProject.get())), TIME_WAIT);
+      assertZoneOperationDoneSucessfully(diskApi().createInZone
+              ("instance-live-test-disk", 10, DEFAULT_ZONE_NAME), TIME_WAIT);
 
-      assertOperationDoneSucessfully(api().createInZone(INSTANCE_NAME, instance, DEFAULT_ZONE_NAME), TIME_WAIT);
+      assertZoneOperationDoneSucessfully(api().createInZone(INSTANCE_NAME, DEFAULT_ZONE_NAME, instance), TIME_WAIT);
 
    }
 
    @Test(groups = "live", dependsOnMethods = "testInsertInstance")
    public void testGetInstance() {
 
-      Instance instance = api().get(INSTANCE_NAME);
+      Instance instance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
       assertNotNull(instance);
       assertInstanceEquals(instance, this.instance);
    }
 
+   @Test(groups = "live", dependsOnMethods = "testListInstance")
+   public void testSetMetadataForInstance() {
+      Instance originalInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+      assertZoneOperationDoneSucessfully(api().setMetadataInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME,
+              ImmutableMap.of(METADATA_ITEM_KEY, METADATA_ITEM_VALUE),
+              originalInstance.getMetadata().getFingerprint()),
+              TIME_WAIT);
+
+      Instance modifiedInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+
+      assertTrue(modifiedInstance.getMetadata().getItems().containsKey(METADATA_ITEM_KEY));
+      assertEquals(modifiedInstance.getMetadata().getItems().get(METADATA_ITEM_KEY),
+              METADATA_ITEM_VALUE);
+      assertNotNull(modifiedInstance.getMetadata().getFingerprint());
+
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testSetMetadataForInstance")
+   public void testAttachDiskToInstance() {
+      assertZoneOperationDoneSucessfully(diskApi().createInZone(ATTACH_DISK_NAME, 1, DEFAULT_ZONE_NAME), TIME_WAIT);
+
+      Instance originalInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+      assertZoneOperationDoneSucessfully(api().attachDiskInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME,
+              new AttachDiskOptions().type(DiskType.PERSISTENT)
+                      .source(getDiskUrl(userProject.get(), ATTACH_DISK_NAME))
+                      .mode(DiskMode.READ_ONLY)
+                      .deviceName(ATTACH_DISK_DEVICE_NAME)),
+              TIME_WAIT);
+
+      Instance modifiedInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+
+      assertTrue(modifiedInstance.getDisks().size() > originalInstance.getDisks().size());
+      assertTrue(Iterables.any(modifiedInstance.getDisks(), new Predicate<AttachedDisk>() {
+
+         @Override
+         public boolean apply(AttachedDisk disk) {
+            return disk instanceof PersistentAttachedDisk &&
+                    ((PersistentAttachedDisk) disk).getDeviceName().orNull().equals(ATTACH_DISK_DEVICE_NAME);
+         }
+      }));
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testAttachDiskToInstance")
+   public void testDetachDiskFromInstance() {
+      Instance originalInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+      assertZoneOperationDoneSucessfully(api().detachDiskInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME,
+              ATTACH_DISK_DEVICE_NAME), TIME_WAIT);
+
+      Instance modifiedInstance = api().getInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME);
+
+      assertTrue(modifiedInstance.getDisks().size() < originalInstance.getDisks().size());
+
+      assertZoneOperationDoneSucessfully(diskApi().deleteInZone(DEFAULT_ZONE_NAME, ATTACH_DISK_NAME), TIME_WAIT);
+   }
+
    @Test(groups = "live", dependsOnMethods = "testInsertInstance")
    public void testListInstance() {
 
-      PagedIterable<Instance> instances = api().list(new ListOptions.Builder()
+      PagedIterable<Instance> instances = api().listInZone(DEFAULT_ZONE_NAME, new ListOptions.Builder()
               .filter("name eq " + INSTANCE_NAME));
 
       List<Instance> instancesAsList = Lists.newArrayList(instances.concat());
@@ -102,19 +193,24 @@ public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
    }
 
-   @Test(groups = "live", dependsOnMethods = "testListInstance")
+   @Test(groups = "live", dependsOnMethods = "testDetachDiskFromInstance")
+   public void testResetInstance() {
+      assertZoneOperationDoneSucessfully(api().resetInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME),
+              TIME_WAIT);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testResetInstance")
    public void testDeleteInstance() {
 
-      assertOperationDoneSucessfully(api().delete(INSTANCE_NAME), TIME_WAIT);
-      assertOperationDoneSucessfully(api.getDiskApiForProject(userProject.get()).delete(DISK_NAME),
+      assertZoneOperationDoneSucessfully(api().deleteInZone(DEFAULT_ZONE_NAME, INSTANCE_NAME), TIME_WAIT);
+      assertZoneOperationDoneSucessfully(api.getDiskApiForProject(userProject.get()).deleteInZone(DEFAULT_ZONE_NAME, DISK_NAME),
               TIME_WAIT);
-      assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
               (INSTANCE_NETWORK_NAME), TIME_WAIT);
    }
 
    private void assertInstanceEquals(Instance result, InstanceTemplate expected) {
       assertEquals(result.getName(), expected.getName());
-      assertEquals(result.getTags(), expected.getTags());
-      assertEquals(result.getMetadata(), expected.getMetadata());
+      assertEquals(result.getMetadata().getItems(), expected.getMetadata());
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiExpectTest.java
index 89e3958..d6f2f5c 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiExpectTest.java
@@ -16,6 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseKernelListTest;
 import org.jclouds.googlecomputeengine.parse.ParseKernelTest;
@@ -23,11 +28,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.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 /**
  * @author David Alves
  */
@@ -39,7 +39,7 @@ public class KernelApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/kernels/12941177846308850718")
+                      ".com/compute/v1beta15/projects/myproject/global/kernels/12941177846308850718")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -58,7 +58,7 @@ public class KernelApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/kernels/12941177846308850718")
+                      ".com/compute/v1beta15/projects/myproject/global/kernels/12941177846308850718")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -75,7 +75,7 @@ public class KernelApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/kernels")
+                      ".com/compute/v1beta15/projects/myproject/global/kernels")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -94,7 +94,7 @@ public class KernelApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/kernels")
+                      ".com/compute/v1beta15/projects/myproject/global/kernels")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiLiveTest.java
index f1476f8..8e9f971 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/KernelApiLiveTest.java
@@ -16,8 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.Kernel;
@@ -25,13 +31,8 @@ import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTe
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
-import java.util.Iterator;
-import java.util.List;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 /**
  * @author David Alves


[07/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RouteApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RouteApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RouteApi.java
new file mode 100644
index 0000000..1eac669
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RouteApi.java
@@ -0,0 +1,185 @@
+/*
+ * 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 java.net.URI;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+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.domain.Route;
+import org.jclouds.googlecomputeengine.functions.internal.ParseRoutes;
+import org.jclouds.googlecomputeengine.handlers.RouteBinder;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+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.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+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 Routes via their REST API.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/routess"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface RouteApi {
+
+   /**
+    * Returns the specified route resource
+    *
+    * @param routeName name of the region resource to return.
+    * @return If successful, this method returns a Route resource
+    */
+   @Named("Routes:get")
+   @GET
+   @Path("/global/routes/{route}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   Route get(@PathParam("route") String routeName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RouteApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Routes:list")
+   @GET
+   @Path("/global/routes")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRoutes.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Route> listFirstPage();
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RouteApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Routes:list")
+   @GET
+   @Path("/global/routes")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRoutes.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Route> listAtMarker(String marker);
+
+   /**
+    * Retrieves the listFirstPage of route resources available to 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 marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the listFirstPage
+    * @see org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("Routes:list")
+   @GET
+   @Path("/global/routes")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRoutes.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Route> listAtMarker(String marker, ListOptions listOptions);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RouteApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Routes:list")
+   @GET
+   @Path("/global/routes")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRoutes.class)
+   @Transform(ParseRoutes.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Route> list();
+
+   /**
+    * A paged version of RegionApi#listFirstPage()
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.googlecomputeengine.features.RouteApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see org.jclouds.collect.PagedIterable
+    */
+   @Named("Routes:list")
+   @GET
+   @Path("/global/routes")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRoutes.class)
+   @Transform(ParseRoutes.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Route> list(ListOptions listOptions);
+
+   /**
+    * Deletes the specified route resource.
+    *
+    * @param routeName name of the route resource to delete.
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.  If the route did not exist the result is null.
+    */
+   @Named("Routes:delete")
+   @DELETE
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/routes/{route}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation delete(@PathParam("route") String routeName);
+
+   /**
+    * Creates a route resource in the specified project using the data included in the request.
+    *
+    * @param name            the name of the route to be inserted.
+    * @param network         the network to which to add the route
+    * @param routeOptions the options of the route to add
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Routes:insert")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/global/routes")
+   @OAuthScopes({COMPUTE_SCOPE})
+   @MapBinder(RouteBinder.class)
+   Operation createInNetwork(@PayloadParam("name") String name,
+                             @PayloadParam("network") URI network,
+                             @PayloadParam("options") RouteOptions routeOptions);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/SnapshotApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/SnapshotApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/SnapshotApi.java
new file mode 100644
index 0000000..6af9a9f
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/SnapshotApi.java
@@ -0,0 +1,161 @@
+/*
+ * 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.domain.Snapshot;
+import org.jclouds.googlecomputeengine.functions.internal.ParseSnapshots;
+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 Snapshots via their REST API.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/snapshots"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+public interface SnapshotApi {
+
+   /**
+    * Returns the specified snapshot resource.
+    *
+    * @param snapshotName name of the snapshot resource to return.
+    * @return a Snapshot resource.
+    */
+   @Named("Snapshots:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots/{snapshot}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Snapshot get(@PathParam("snapshot") String snapshotName);
+
+   /**
+    * Deletes the specified snapshot resource.
+    *
+    * @param snapshotName name of the snapshot resource to delete.
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Snapshots:delete")
+   @DELETE
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots/{snapshot}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation delete(@PathParam("snapshot") String snapshotName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.SnapshotApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Snapshots:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseSnapshots.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Snapshot> listFirstPage();
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.SnapshotApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Snapshots:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseSnapshots.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Snapshot> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
+
+   /**
+    * Retrieves the listPage of persistent disk resources contained within the specified project and zone.
+    * By default the listPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has
+    * not been set.
+    *
+    * @param marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the listPage
+    * @see org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("Snapshots:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseSnapshots.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Snapshot> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions listOptions);
+
+   /**
+    * A paged version of SnapshotApi#listPage(String)
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.collect.PagedIterable
+    * @see org.jclouds.googlecomputeengine.features.SnapshotApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Snapshots:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseSnapshots.class)
+   @Transform(ParseSnapshots.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Snapshot> list();
+
+   @Named("Snapshots:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/global/snapshots")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseSnapshots.class)
+   @Transform(ParseSnapshots.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Snapshot> list(ListOptions options);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneApi.java
index fcf9618..0542842 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ZoneApi.java
@@ -45,7 +45,7 @@ import org.jclouds.rest.annotations.Transform;
  * Provides access to Zones via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/zones"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithRegionToPagedIterable.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithRegionToPagedIterable.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithRegionToPagedIterable.java
new file mode 100644
index 0000000..3c348c4
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/BaseWithRegionToPagedIterable.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 BaseWithRegionToPagedIterable<T, I extends BaseWithRegionToPagedIterable<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> region = tryFind(request.getInvocation().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 region.isPresent() : String.format("programming error, method %s should have a string param for the "
+              + "region", request.getCaller().get().getInvokable());
+
+      return PagedIterables.advance(
+              input, fetchNextPage(project.get().toString(), region.get().toString(), (ListOptions) listOptions.orNull()));
+   }
+
+   protected abstract Function<Object, IterableWithMarker<T>> fetchNextPage(String projectName,
+                                                                            String regionName,
+                                                                            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-google/blob/53386380/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..1f5317b
--- /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.getInvocation().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-google/blob/53386380/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-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseAddresses.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseAddresses.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseAddresses.java
new file mode 100644
index 0000000..c59afaa
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseAddresses.java
@@ -0,0 +1,70 @@
+/*
+ * 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 javax.inject.Singleton;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.Address;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+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 Andrew Bayer
+ */
+@Singleton
+public class ParseAddresses extends ParseJson<ListPage<Address>> {
+
+   @Inject
+   public ParseAddresses(Json json) {
+      super(json, new TypeLiteral<ListPage<Address>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseWithRegionToPagedIterable<Address, ToPagedIterable> {
+
+      private final GoogleComputeEngineApi api;
+
+      @Inject
+      protected ToPagedIterable(GoogleComputeEngineApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      @Override
+      protected Function<Object, IterableWithMarker<Address>> fetchNextPage(final String projectName,
+                                                                            final String regionName,
+                                                                         final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Address>>() {
+
+            @Override
+            public IterableWithMarker<Address> apply(Object input) {
+               return api.getAddressApiForProject(projectName)
+                       .listAtMarkerInRegion(regionName, input.toString(), options);
+            }
+         };
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegionOperations.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegionOperations.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegionOperations.java
new file mode 100644
index 0000000..23b2327
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegionOperations.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 ParseRegionOperations extends ParseJson<ListPage<Operation>> {
+
+   @Inject
+   public ParseRegionOperations(Json json) {
+      super(json, new TypeLiteral<ListPage<Operation>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseWithRegionToPagedIterable<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 regionName,
+                                                                              final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Operation>>() {
+
+            @Override
+            public IterableWithMarker<Operation> apply(Object input) {
+               return api.getRegionOperationApiForProject(projectName)
+                       .listAtMarkerInRegion(regionName, input.toString(), options);
+            }
+         };
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegions.java
new file mode 100644
index 0000000..fbc97ab
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRegions.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.Region;
+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 ParseRegions extends ParseJson<ListPage<Region>> {
+
+   @Inject
+   public ParseRegions(Json json) {
+      super(json, new TypeLiteral<ListPage<Region>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseToPagedIterable<Region, ToPagedIterable> {
+
+      private final GoogleComputeEngineApi api;
+
+      @Inject
+      protected ToPagedIterable(GoogleComputeEngineApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      @Override
+      protected Function<Object, IterableWithMarker<Region>> fetchNextPage(final String projectName,
+                                                                           final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Region>>() {
+
+            @Override
+            public IterableWithMarker<Region> apply(Object input) {
+               return api.getRegionApiForProject(projectName).listAtMarker(input.toString(), options);
+            }
+         };
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRoutes.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRoutes.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRoutes.java
new file mode 100644
index 0000000..6207294
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/functions/internal/ParseRoutes.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.Route;
+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 Andrew Bayer
+ */
+public class ParseRoutes extends ParseJson<ListPage<Route>> {
+
+   @Inject
+   public ParseRoutes(Json json) {
+      super(json, new TypeLiteral<ListPage<Route>>() {
+      });
+   }
+
+   public static class ToPagedIterable extends BaseToPagedIterable<Route, ToPagedIterable> {
+
+      private final GoogleComputeEngineApi api;
+
+      @Inject
+      protected ToPagedIterable(GoogleComputeEngineApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      @Override
+      protected Function<Object, IterableWithMarker<Route>> fetchNextPage(final String projectName,
+                                                                          final ListOptions options) {
+         return new Function<Object, IterableWithMarker<Route>>() {
+
+            @Override
+            public IterableWithMarker<Route> apply(Object input) {
+               return api.getRouteApiForProject(projectName).listAtMarker(input.toString(), options);
+            }
+         };
+      }
+   }
+}

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

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/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..87a2b68 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,28 +16,47 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
-import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.Binder;
-import org.jclouds.rest.binders.BindToJsonPayload;
+import static com.google.common.base.Preconditions.checkNotNull;
 
-import javax.inject.Inject;
 import java.util.Map;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import javax.inject.Inject;
+
+import org.jclouds.googlecomputeengine.domain.Metadata;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import com.google.common.collect.ImmutableMap;
 
 /**
  * @author David Alves
  */
-public class MetadataBinder implements Binder {
+public class MetadataBinder implements MapBinder {
 
    @Inject
    private BindToJsonPayload jsonBinder;
 
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      Map<String, String> items = ImmutableMap.copyOf((Map<String,String>)checkNotNull(postParams.get("items"), "item"));
+      String fingerprint = (String) checkNotNull(postParams.get("fingerprint"), "fingerprint");
+      Metadata metadata = Metadata.builder()
+              .fingerprint(fingerprint)
+              .items(items)
+              .build();
+      return bindToRequest(request, metadata);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
    @Override
-   @SuppressWarnings("unchecked")
    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
-      Map<String, String> metadataEntries = (Map<String, String>) checkNotNull(input, "input metadata");
-      return jsonBinder.bindToRequest(request, new GoogleComputeEngineParserModule.Metadata(metadataEntries));
+      return jsonBinder.bindToRequest(request, input);
    }
+
 }


[09/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceInZone.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceInZone.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceInZone.java
new file mode 100644
index 0000000..18f8e5b
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceInZone.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+/**
+ * @author Adam Lowe
+ */
+public class InstanceInZone extends SlashEncodedIds {
+   protected final Instance instance;
+
+   public InstanceInZone(Instance instance, String zoneId) {
+      super(zoneId, checkNotNull(instance, "instance").getName());
+      this.instance = instance;
+   }
+
+   public Instance getInstance() {
+      return instance;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      InstanceInZone that = InstanceInZone.class.cast(obj);
+      return equal(this.instance, that.instance)
+              && equal(this.firstId, that.firstId)
+              && equal(this.secondId, that.secondId);
+   }
+
+   @Override
+   public String toString() {
+      return "[instance=" + instance + ", zoneId=" + firstId + "]";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceTemplate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceTemplate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceTemplate.java
index de93d7c..a8d52c2 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceTemplate.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/InstanceTemplate.java
@@ -16,18 +16,18 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
 
 import java.net.URI;
 import java.util.Map;
 import java.util.Set;
 
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 /**
  * Optional information for creating an instance.
@@ -39,16 +39,13 @@ public class InstanceTemplate {
    protected String name;
    protected String description;
    protected URI machineType;
-   protected URI zone;
    protected URI image;
-   protected Set<String> tags = Sets.newLinkedHashSet();
    protected Set<Instance.ServiceAccount> serviceAccounts = Sets.newLinkedHashSet();
 
    protected transient Set<PersistentDisk> disks = Sets.newLinkedHashSet();
    protected transient Set<NetworkInterface> networkInterfaces = Sets.newLinkedHashSet();
    protected transient Map<String, String> metadata = Maps.newLinkedHashMap();
    protected transient String machineTypeName;
-   protected transient String zoneName;
 
 
    protected InstanceTemplate(URI machineType) {
@@ -100,39 +97,6 @@ public class InstanceTemplate {
    }
 
    /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
-    */
-   public InstanceTemplate zone(String zoneName) {
-      this.zoneName = zoneName;
-      return this;
-   }
-
-   /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
-    */
-   public InstanceTemplate zone(URI zone) {
-      this.zone = zone;
-      return this;
-   }
-
-   /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
-    */
-   public InstanceTemplate addTag(String tag) {
-      this.tags.add(checkNotNull(tag, "tag"));
-      return this;
-   }
-
-   /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
-    */
-   public InstanceTemplate tags(Set<String> tags) {
-      this.tags = Sets.newLinkedHashSet();
-      this.tags.addAll(checkNotNull(tags, "tags"));
-      return this;
-   }
-
-   /**
     * @see org.jclouds.googlecomputeengine.domain.Instance#getDisks()
     */
    public InstanceTemplate addDisk(PersistentDisk.Mode mode, URI source) {
@@ -161,7 +125,7 @@ public class InstanceTemplate {
     * @see org.jclouds.googlecomputeengine.domain.Instance#getNetworkInterfaces()
     */
    public InstanceTemplate addNetworkInterface(URI network) {
-      this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null,null));
+      this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null, null));
       return this;
    }
 
@@ -281,33 +245,12 @@ public class InstanceTemplate {
    }
 
    /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
-    */
-   public Set<String> getTags() {
-      return tags;
-   }
-
-   /**
     * @see org.jclouds.googlecomputeengine.domain.Instance#getName()
     */
    public String getName() {
       return name;
    }
 
-   /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
-    */
-   public URI getZone() {
-      return zone;
-   }
-
-   /**
-    * @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
-    */
-   public String getZoneName() {
-      return zoneName;
-   }
-
    public static Builder builder() {
       return new Builder();
    }
@@ -332,9 +275,7 @@ public class InstanceTemplate {
                  .networkInterfaces(instanceTemplate.getNetworkInterfaces())
                  .name(instanceTemplate.getName())
                  .description(instanceTemplate.getDescription())
-                 .zone(instanceTemplate.getZone())
                  .image(instanceTemplate.getImage())
-                 .tags(instanceTemplate.getTags())
                  .disks(instanceTemplate.getDisks())
                  .metadata(instanceTemplate.getMetadata())
                  .serviceAccounts(instanceTemplate.getServiceAccounts());
@@ -431,7 +372,6 @@ public class InstanceTemplate {
       if (object instanceof InstanceTemplate) {
          final InstanceTemplate other = InstanceTemplate.class.cast(object);
          return equal(description, other.description)
-                 && equal(tags, other.tags)
                  && equal(image, other.image)
                  && equal(disks, other.disks)
                  && equal(networkInterfaces, other.networkInterfaces)
@@ -447,7 +387,7 @@ public class InstanceTemplate {
     */
    @Override
    public int hashCode() {
-      return Objects.hashCode(description, tags, image, disks, networkInterfaces, metadata, serviceAccounts);
+      return Objects.hashCode(description, image, disks, networkInterfaces, metadata, serviceAccounts);
    }
 
    /**
@@ -457,8 +397,6 @@ public class InstanceTemplate {
       Objects.ToStringHelper toString = Objects.toStringHelper("")
               .omitNullValues();
       toString.add("description", description);
-      if (tags.size() > 0)
-         toString.add("tags", tags);
       if (disks.size() > 0)
          toString.add("disks", disks);
       if (metadata.size() > 0)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Kernel.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Kernel.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Kernel.java
index 9256a9f..1834078 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Kernel.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Kernel.java
@@ -16,26 +16,40 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
+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 com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+
 /**
  * Represents a kernel.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/kernels"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/kernels"/>
  */
 @Beta
 public final class Kernel extends Resource {
+   private final Optional<Deprecated> deprecated;
 
    @ConstructorProperties({
-           "id", "creationTimestamp", "selfLink", "name", "description"
+           "id", "creationTimestamp", "selfLink", "name", "description", "deprecated"
    })
-   private Kernel(String id, Date creationTimestamp, URI selfLink, String name, String description) {
+   private Kernel(String id, Date creationTimestamp, URI selfLink, String name, String description,
+                  Deprecated deprecated) {
       super(Kind.KERNEL, id, creationTimestamp, selfLink, name, description);
+      this.deprecated = fromNullable(deprecated);
+   }
+
+   /**
+    * @return the deprecation information for this kernel
+    */
+   public Optional<Deprecated> getDeprecated() {
+      return deprecated;
    }
 
    public static Builder builder() {
@@ -48,6 +62,16 @@ public final class Kernel extends Resource {
 
    public static final class Builder extends Resource.Builder<Builder> {
 
+      private Deprecated deprecated;
+
+      /**
+       * @see Kernel#getDeprecated()
+       */
+      public Builder deprecated(Deprecated deprecated) {
+         this.deprecated = checkNotNull(deprecated, "deprecated");
+         return this;
+      }
+
       @Override
       protected Builder self() {
          return this;
@@ -55,11 +79,12 @@ public final class Kernel extends Resource {
 
       public Kernel build() {
          return new Kernel(super.id, super.creationTimestamp, super.selfLink, super.name,
-                 super.description);
+                 super.description, deprecated);
       }
 
       public Builder fromKernel(Kernel in) {
-         return super.fromResource(in);
+         return super.fromResource(in)
+                 .deprecated(in.getDeprecated().orNull());
       }
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ListPage.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ListPage.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ListPage.java
index bca5711..98660c3 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ListPage.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/ListPage.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.collect.IterableWithMarker;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.googlecomputeengine.domain.Resource.Kind;
 
 import java.beans.ConstructorProperties;
 import java.net.URI;
 import java.util.Iterator;
 
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.jclouds.googlecomputeengine.domain.Resource.Kind;
+import org.jclouds.collect.IterableWithMarker;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * The collection returned from any <code>listFirstPage()</code> method.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineType.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineType.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineType.java
index d106b9b..fd1aa58 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineType.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineType.java
@@ -16,26 +16,24 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.beans.ConstructorProperties;
 import java.net.URI;
 import java.util.Date;
 import java.util.List;
-import java.util.Set;
 
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
 
 /**
  * Represents a machine type used to host an instance.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/machineTypes"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/machineTypes"/>
  */
 @Beta
 public final class MachineType extends Resource {
@@ -43,26 +41,26 @@ public final class MachineType extends Resource {
    private final Integer guestCpus;
    private final Integer memoryMb;
    private final Integer imageSpaceGb;
-   private final List<EphemeralDisk> ephemeralDisks;
+   private final List<ScratchDisk> scratchDisks;
    private final Integer maximumPersistentDisks;
    private final Long maximumPersistentDisksSizeGb;
-   private final Set<String> availableZone;
+   private final String zone;
 
    @ConstructorProperties({
            "id", "creationTimestamp", "selfLink", "name", "description", "guestCpus", "memoryMb",
-           "imageSpaceGb", "ephemeralDisks", "maximumPersistentDisks", "maximumPersistentDisksSizeGb", "availableZone"
+           "imageSpaceGb", "scratchDisks", "maximumPersistentDisks", "maximumPersistentDisksSizeGb", "zone"
    })
    private MachineType(String id, Date creationTimestamp, URI selfLink, String name, String description,
-                       int guestCpus, int memoryMb, int imageSpaceGb, List<EphemeralDisk> ephemeralDisks,
-                       int maximumPersistentDisks, long maximumPersistentDisksSizeGb, Set<String> availableZone) {
+                       int guestCpus, int memoryMb, int imageSpaceGb, List<ScratchDisk> scratchDisks,
+                       int maximumPersistentDisks, long maximumPersistentDisksSizeGb, String zone) {
       super(Kind.MACHINE_TYPE, id, creationTimestamp, selfLink, name, description);
       this.guestCpus = checkNotNull(guestCpus, "guestCpus of %s", name);
       this.memoryMb = checkNotNull(memoryMb, "memoryMb of %s", name);
       this.imageSpaceGb = checkNotNull(imageSpaceGb, "imageSpaceGb of %s", name);
-      this.ephemeralDisks = ephemeralDisks == null ? ImmutableList.<EphemeralDisk>of() : ephemeralDisks;
+      this.scratchDisks = scratchDisks == null ? ImmutableList.<ScratchDisk>of() : scratchDisks;
       this.maximumPersistentDisks = checkNotNull(maximumPersistentDisks, "maximumPersistentDisks of %s", name);
       this.maximumPersistentDisksSizeGb = maximumPersistentDisksSizeGb;
-      this.availableZone = availableZone == null ? ImmutableSet.<String>of() : availableZone;
+      this.zone = checkNotNull(zone, "zone of %s", name);
    }
 
    /**
@@ -87,10 +85,10 @@ public final class MachineType extends Resource {
    }
 
    /**
-    * @return extended ephemeral disks assigned to the instance.
+    * @return extended scratch disks assigned to the instance.
     */
-   public List<EphemeralDisk> getEphemeralDisks() {
-      return ephemeralDisks;
+   public List<ScratchDisk> getScratchDisks() {
+      return scratchDisks;
    }
 
    /**
@@ -110,8 +108,21 @@ public final class MachineType extends Resource {
    /**
     * @return the zones that this machine type can run in.
     */
-   public Set<String> getAvailableZone() {
-      return availableZone;
+   public String getZone() {
+      return zone;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      MachineType that = MachineType.class.cast(obj);
+      return equal(this.kind, that.kind)
+              && equal(this.name, that.name)
+              && equal(this.zone, that.zone);
    }
 
    /**
@@ -122,10 +133,10 @@ public final class MachineType extends Resource {
               .add("guestCpus", guestCpus)
               .add("memoryMb", memoryMb)
               .add("imageSpaceGb", imageSpaceGb)
-              .add("ephemeralDisks", ephemeralDisks)
+              .add("scratchDisks", scratchDisks)
               .add("maximumPersistentDisks", maximumPersistentDisks)
               .add("maximumPersistentDisksSizeGb", maximumPersistentDisksSizeGb)
-              .add("availableZone", availableZone);
+              .add("zone", zone);
    }
 
    /**
@@ -149,10 +160,10 @@ public final class MachineType extends Resource {
       private Integer guestCpus;
       private Integer memoryMb;
       private Integer imageSpaceGb;
-      private ImmutableList.Builder<EphemeralDisk> ephemeralDisks = ImmutableList.builder();
+      private ImmutableList.Builder<ScratchDisk> scratchDisks = ImmutableList.builder();
       private Integer maximumPersistentDisks;
       private Long maximumPersistentDisksSizeGb;
-      private ImmutableSet.Builder<String> availableZone = ImmutableSet.builder();
+      private String zone;
 
       /**
        * @see MachineType#getGuestCpus()
@@ -179,18 +190,18 @@ public final class MachineType extends Resource {
       }
 
       /**
-       * @see MachineType#getEphemeralDisks()
+       * @see MachineType#getScratchDisks()
        */
-      public Builder addEphemeralDisk(int diskGb) {
-         this.ephemeralDisks.add(EphemeralDisk.builder().diskGb(diskGb).build());
+      public Builder addScratchDisk(int diskGb) {
+         this.scratchDisks.add(ScratchDisk.builder().diskGb(diskGb).build());
          return this;
       }
 
       /**
-       * @see MachineType#getEphemeralDisks()
+       * @see MachineType#getScratchDisks()
        */
-      public Builder ephemeralDisks(List<EphemeralDisk> ephemeralDisks) {
-         this.ephemeralDisks.addAll(ephemeralDisks);
+      public Builder scratchDisks(List<ScratchDisk> scratchDisks) {
+         this.scratchDisks.addAll(scratchDisks);
          return this;
       }
 
@@ -211,18 +222,10 @@ public final class MachineType extends Resource {
       }
 
       /**
-       * @see MachineType#getAvailableZone()
-       */
-      public Builder addAvailableZone(String availableZone) {
-         this.availableZone.add(availableZone);
-         return this;
-      }
-
-      /**
-       * @see MachineType#getAvailableZone()
+       * @see MachineType#getZone()
        */
-      public Builder availableZones(Set<String> availableZone) {
-         this.availableZone.addAll(availableZone);
+      public Builder zone(String zone) {
+         this.zone = zone;
          return this;
       }
 
@@ -233,35 +236,35 @@ public final class MachineType extends Resource {
 
       public MachineType build() {
          return new MachineType(id, creationTimestamp, selfLink, name, description, guestCpus, memoryMb,
-                 imageSpaceGb, ephemeralDisks.build(), maximumPersistentDisks, maximumPersistentDisksSizeGb,
-                 availableZone.build());
+                 imageSpaceGb, scratchDisks.build(), maximumPersistentDisks, maximumPersistentDisksSizeGb,
+                 zone);
       }
 
 
       public Builder fromMachineType(MachineType in) {
-         return super.fromResource(in).memoryMb(in.getMemoryMb()).imageSpaceGb(in.getImageSpaceGb()).ephemeralDisks(in
-                 .getEphemeralDisks()).maximumPersistentDisks(in.getMaximumPersistentDisks())
-                 .maximumPersistentDisksSizeGb(in.getMaximumPersistentDisksSizeGb()).availableZones(in
-                         .getAvailableZone());
+         return super.fromResource(in).memoryMb(in.getMemoryMb()).imageSpaceGb(in.getImageSpaceGb()).scratchDisks(in
+                 .getScratchDisks()).maximumPersistentDisks(in.getMaximumPersistentDisks())
+                 .maximumPersistentDisksSizeGb(in.getMaximumPersistentDisksSizeGb()).zone(in
+                         .getZone());
       }
    }
 
    /**
-    * An ephemeral disk of a MachineType
+    * An scratch disk of a MachineType
     */
-   public static final class EphemeralDisk {
+   public static final class ScratchDisk {
 
       private final int diskGb;
 
       @ConstructorProperties({
               "diskGb"
       })
-      private EphemeralDisk(int diskGb) {
+      private ScratchDisk(int diskGb) {
          this.diskGb = diskGb;
       }
 
       /**
-       * @return size of the ephemeral disk, defined in GB.
+       * @return size of the scratch disk, defined in GB.
        */
       public int getDiskGb() {
          return diskGb;
@@ -282,7 +285,7 @@ public final class MachineType extends Resource {
       public boolean equals(Object obj) {
          if (this == obj) return true;
          if (obj == null || getClass() != obj.getClass()) return false;
-         EphemeralDisk that = EphemeralDisk.class.cast(obj);
+         ScratchDisk that = ScratchDisk.class.cast(obj);
          return equal(this.diskGb, that.diskGb);
       }
 
@@ -307,7 +310,7 @@ public final class MachineType extends Resource {
       }
 
       public Builder toBuilder() {
-         return builder().fromEphemeralDisk(this);
+         return builder().fromScratchDisk(this);
       }
 
       public static class Builder {
@@ -315,18 +318,18 @@ public final class MachineType extends Resource {
          private int diskGb;
 
          /**
-          * @see org.jclouds.googlecomputeengine.domain.MachineType.EphemeralDisk#getDiskGb()
+          * @see org.jclouds.googlecomputeengine.domain.MachineType.ScratchDisk#getDiskGb()
           */
          public Builder diskGb(int diskGb) {
             this.diskGb = diskGb;
             return this;
          }
 
-         public EphemeralDisk build() {
-            return new EphemeralDisk(diskGb);
+         public ScratchDisk build() {
+            return new ScratchDisk(diskGb);
          }
 
-         public Builder fromEphemeralDisk(EphemeralDisk in) {
+         public Builder fromScratchDisk(ScratchDisk in) {
             return new Builder().diskGb(in.getDiskGb());
          }
       }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineTypeInZone.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineTypeInZone.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineTypeInZone.java
new file mode 100644
index 0000000..2ba3d49
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/MachineTypeInZone.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+/**
+ * @author Adam Lowe
+ */
+public class MachineTypeInZone extends SlashEncodedIds {
+   protected final MachineType machineType;
+
+   public MachineTypeInZone(MachineType machineType, String zoneId) {
+      super(zoneId, checkNotNull(machineType, "machineType").getName());
+      this.machineType = machineType;
+   }
+
+   public MachineType getMachineType() {
+      return machineType;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      MachineTypeInZone that = MachineTypeInZone.class.cast(obj);
+      return equal(this.machineType, that.machineType)
+              && equal(this.firstId, that.firstId)
+              && equal(this.secondId, that.secondId);
+   }
+
+   @Override
+   public String toString() {
+      return "[machineType=" + machineType + ", zoneId=" + firstId + "]";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
new file mode 100644
index 0000000..66c6636
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Metadata.java
@@ -0,0 +1,140 @@
+/*
+ * 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 java.beans.ConstructorProperties;
+import java.util.Map;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Metadata for an instance or project, with their fingerprint.
+ * @author Andrew Bayer
+ */
+public class Metadata {
+   @Nullable
+   private final String fingerprint;
+   private final Map<String, String> items;
+
+   @ConstructorProperties({"fingerprint", "items"})
+   public Metadata(@Nullable String fingerprint, @Nullable Map<String, String> items) {
+      this.fingerprint = fingerprint;
+      this.items = items == null ? ImmutableMap.<String,String>of() : items;
+   }
+
+   /**
+    * @return an optional map of metadata key/value pairs for this instance/project
+    */
+   public Map<String, String> getItems() {
+      return items;
+   }
+
+   /**
+    * Gets the fingerprint for the items - needed for updating them.
+    *
+    * @return the fingerprint string for the items.
+    */
+   public String getFingerprint() {
+      return fingerprint;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(fingerprint, items);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Metadata that = Metadata.class.cast(obj);
+      return equal(this.items, that.items)
+              && equal(this.fingerprint, that.fingerprint);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return toStringHelper(this)
+              .add("items", items)
+              .add("fingerprint", fingerprint);
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static final class Builder {
+
+      private ImmutableMap.Builder<String,String> items = ImmutableMap.builder();
+      private String fingerprint;
+
+      /**
+       * @see Metadata#getItems()
+       */
+      public Builder addItem(String key, String value) {
+         this.items.put(key, value);
+         return this;
+      }
+
+      /**
+       * @see Metadata#getItems()
+       */
+      public Builder items(Map<String, String> items) {
+         this.items.putAll(items);
+         return this;
+      }
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Metadata#getFingerprint()
+       */
+      public Builder fingerprint(String fingerprint) {
+         this.fingerprint = fingerprint;
+         return this;
+      }
+
+      public Metadata build() {
+         return new Metadata(this.fingerprint, this.items.build());
+      }
+
+      public Builder fromMetadata(Metadata in) {
+         return this.fingerprint(in.getFingerprint())
+                 .items(in.getItems());
+      }
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Network.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Network.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Network.java
index c862798..2fe913c 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Network.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Network.java
@@ -17,22 +17,22 @@
 package org.jclouds.googlecomputeengine.domain;
 
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
+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 static com.google.common.base.Optional.fromNullable;
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
 
 /**
  * Represents a network used to enable instance communication.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/networks"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/networks"/>
  */
 @Beta
 public final class Network extends Resource {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Operation.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Operation.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Operation.java
index cf685ed..f387aee 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Operation.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Operation.java
@@ -16,27 +16,29 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import org.jclouds.http.HttpResponse;
+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.List;
 
-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 org.jclouds.http.HttpResponse;
+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.ImmutableList;
 
 /**
  * Describes an operation being executed on some Resource
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/operations"/>
  */
 @Beta
 public class Operation extends Resource {
@@ -60,12 +62,14 @@ public class Operation extends Resource {
    private final Optional<HttpResponse> httpError;
    private final String operationType;
    private final List<Error> errors;
+   private final Optional<URI> zone;
+   private final Optional<URI> region;
 
    protected Operation(String id, Date creationTimestamp, URI selfLink, String name, String description,
                        URI targetLink, String targetId, String clientOperationId, Status status,
                        String statusMessage, String user, Integer progress, Date insertTime, Date startTime,
                        Date endTime, Integer httpErrorStatusCode, String httpErrorMessage, String operationType,
-                       List<Error> errors) {
+                       @Nullable List<Error> errors, URI region, URI zone) {
       super(Kind.OPERATION, id, creationTimestamp, selfLink, name, description);
       this.targetLink = checkNotNull(targetLink, "targetLink of %s", name);
       this.targetId = fromNullable(targetId);
@@ -85,6 +89,8 @@ public class Operation extends Resource {
               : Optional.<HttpResponse>absent();
       this.operationType = checkNotNull(operationType, "insertTime of %s", name);
       this.errors = errors == null ? ImmutableList.<Error>of() : ImmutableList.copyOf(errors);
+      this.region = fromNullable(region);
+      this.zone = fromNullable(zone);
    }
 
    /**
@@ -95,6 +101,14 @@ public class Operation extends Resource {
    }
 
    /**
+    * @return An optional identifier specified by the client when the mutation was initiated. Must be unique for all
+    *         operation resources in the project.
+    */
+   public Optional<String> getClientOperationId() {
+      return clientOperationId;
+   }
+
+   /**
     * @return unique target id which identifies a particular incarnation of the target.
     */
    public Optional<String> getTargetId() {
@@ -102,11 +116,17 @@ public class Operation extends Resource {
    }
 
    /**
-    * @return An optional identifier specified by the client when the mutation was initiated. Must be unique for all
-    *         operation resources in the project.
+    * @return region this operation is in, if any.
     */
-   public Optional<String> getClientOperationId() {
-      return clientOperationId;
+   public Optional<URI> getRegion() {
+      return region;
+   }
+
+   /**
+    * @return zone this operation is in, if any.
+    */
+   public Optional<URI> getZone() {
+      return zone;
    }
 
    /**
@@ -199,7 +219,9 @@ public class Operation extends Resource {
               .add("endTime", endTime.orNull())
               .add("httpError", httpError.orNull())
               .add("operationType", operationType)
-              .add("errors", errors);
+              .add("errors", errors)
+              .add("region", region.orNull())
+              .add("zone", zone.orNull());
    }
 
    /**
@@ -234,6 +256,8 @@ public class Operation extends Resource {
       private String httpErrorMessage;
       private String operationType;
       private ImmutableList.Builder<Error> errors = ImmutableList.builder();
+      private URI region;
+      private URI zone;
 
       /**
        * @see Operation#getTargetLink()
@@ -244,6 +268,22 @@ public class Operation extends Resource {
       }
 
       /**
+       * @see Operation#getRegion()
+       */
+      public Builder region(URI region) {
+         this.region = region;
+         return self();
+      }
+
+      /**
+       * @see Operation#getZone()
+       */
+      public Builder zone(URI zone) {
+         this.zone = zone;
+         return self();
+      }
+
+      /**
        * @see Operation#getTargetId()
        */
       public Builder targetId(String targetId) {
@@ -365,7 +405,7 @@ public class Operation extends Resource {
          return new Operation(super.id, super.creationTimestamp, super.selfLink, super.name,
                  super.description, targetLink, targetId, clientOperationId, status, statusMessage, user, progress,
                  insertTime, startTime, endTime, httpErrorStatusCode, httpErrorMessage, operationType,
-                 errors.build());
+                 errors.build(), region, zone);
       }
 
       public Builder fromOperation(Operation in) {
@@ -382,7 +422,8 @@ public class Operation extends Resource {
                  .endTime(in.getEndTime().orNull())
                  .httpErrorStatusCode(in.getHttpError().isPresent() ? in.getHttpError().get().getStatusCode() : null)
                  .httpErrorMessage(in.getHttpError().isPresent() ? in.getHttpError().get().getMessage() : null)
-                 .operationType(in.getOperationType()).errors(in.getErrors());
+                 .operationType(in.getOperationType()).errors(in.getErrors())
+                 .zone(in.getZone().orNull()).region(in.getRegion().orNull());
       }
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Project.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Project.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Project.java
index 33de1b9..0292c71 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Project.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Project.java
@@ -16,21 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.javax.annotation.Nullable;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+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 static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * A Project resource is the root collection and settings resource for all Google Compute Engine resources.
@@ -41,15 +40,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
 @Beta
 public class Project extends Resource {
 
-   private final Map<String, String> commonInstanceMetadata;
+   private final Metadata commonInstanceMetadata;
    private final Set<Quota> quotas;
    private final Set<String> externalIpAddresses;
 
    protected Project(String id, Date creationTimestamp, URI selfLink, String name, String description,
-                     Map<String, String> commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
+                     Metadata commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
       super(Kind.PROJECT, id, creationTimestamp, selfLink, name, description);
-      this.commonInstanceMetadata = commonInstanceMetadata == null ? ImmutableMap.<String,
-              String>of() : ImmutableMap.copyOf(commonInstanceMetadata);
+      this.commonInstanceMetadata = checkNotNull(commonInstanceMetadata, "commonInstanceMetadata");
       this.quotas = quotas == null ? ImmutableSet.<Quota>of() : ImmutableSet.copyOf(quotas);
       this.externalIpAddresses = externalIpAddresses == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf
               (externalIpAddresses);
@@ -58,7 +56,7 @@ public class Project extends Resource {
    /**
     * @return metadata key/value pairs available to all instances contained in this project.
     */
-   public Map<String, String> getCommonInstanceMetadata() {
+   public Metadata getCommonInstanceMetadata() {
       return commonInstanceMetadata;
    }
 
@@ -105,23 +103,15 @@ public class Project extends Resource {
 
    public static final class Builder extends Resource.Builder<Builder> {
 
-      private ImmutableMap.Builder<String, String> commonInstanceMetadata = ImmutableMap.builder();
+      private Metadata commonInstanceMetadata;
       private ImmutableSet.Builder<Quota> quotas = ImmutableSet.builder();
       private ImmutableSet.Builder<String> externalIpAddresses = ImmutableSet.builder();
 
       /**
        * @see Project#getCommonInstanceMetadata()
        */
-      public Builder addCommonInstanceMetadata(String key, String value) {
-         this.commonInstanceMetadata.put(key, value);
-         return this;
-      }
-
-      /**
-       * @see Project#getCommonInstanceMetadata()
-       */
-      public Builder commonInstanceMetadata(Map<String, String> commonInstanceMetadata) {
-         this.commonInstanceMetadata.putAll(checkNotNull(commonInstanceMetadata, "commonInstanceMetadata"));
+      public Builder commonInstanceMetadata(Metadata commonInstanceMetadata) {
+         this.commonInstanceMetadata = commonInstanceMetadata;
          return this;
       }
 
@@ -164,7 +154,7 @@ public class Project extends Resource {
 
       public Project build() {
          return new Project(super.id, super.creationTimestamp, super.selfLink, super.name,
-                 super.description, commonInstanceMetadata.build(), quotas.build(), externalIpAddresses.build());
+                 super.description, commonInstanceMetadata, quotas.build(), externalIpAddresses.build());
       }
 
       public Builder fromProject(Project in) {
@@ -176,7 +166,7 @@ public class Project extends Resource {
    /**
     * Quotas assigned to a given project
     *
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/projects#resource"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/projects#resource"/>
     */
    public static final class Quota {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Region.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Region.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Region.java
new file mode 100644
index 0000000..582cca2
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Region.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Preconditions.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.collect.ImmutableSet;
+
+/**
+ * Represents a region resource.
+ *
+ * @author David Alves
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/regions"/>
+ */
+@Beta
+public final class Region extends Resource {
+
+   public enum Status {
+      UP,
+      DOWN
+   }
+
+   private final Status status;
+   private final Set<URI> zones;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "status",
+           "zones"
+   })
+   private Region(String id, Date creationTimestamp, URI selfLink, String name, String description,
+                  Status status, Set<URI> zones) {
+      super(Kind.REGION, id, creationTimestamp, selfLink, name, description);
+      this.status = checkNotNull(status, "status of %name", name);
+      this.zones = zones == null ? ImmutableSet.<URI>of() : ImmutableSet
+              .copyOf(zones);
+   }
+
+   /**
+    * @return Status of the region. "UP" or "DOWN".
+    */
+   public Status getStatus() {
+      return status;
+   }
+
+   /**
+    * @return the zones that can be used in this region.
+    */
+   @Nullable
+   public Set<URI> getZones() {
+      return zones;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .add("status", status)
+              .add("zones", zones);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromRegion(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private Status status;
+      private ImmutableSet.Builder<URI> zones = ImmutableSet.builder();
+
+      /**
+       * @see org.jclouds.googlecomputeengine.domain.Region#getStatus()
+       */
+      public Builder status(Status status) {
+         this.status = status;
+         return this;
+      }
+
+      /**
+       * @see Region#getZones()
+       */
+      public Builder zone(URI zone) {
+         this.zones.add(checkNotNull(zone, "zone"));
+         return this;
+      }
+
+      /**
+       * @see Region#getZones()
+       */
+      public Builder zones(Set<URI> zones) {
+         this.zones.addAll(checkNotNull(zones, "zones"));
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public Region build() {
+         return new Region(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, status, zones.build());
+      }
+
+      public Builder fromRegion(Region in) {
+         return super.fromResource(in)
+                 .status(in.getStatus())
+                 .zones(in.getZones());
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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
index 19698d8..8abb381 100644
--- 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
@@ -16,6 +16,18 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
+import static com.google.common.base.Objects.ToStringHelper;
+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 org.jclouds.javax.annotation.Nullable;
+
 import com.google.common.annotations.Beta;
 import com.google.common.base.CaseFormat;
 import com.google.common.base.Joiner;
@@ -23,17 +35,6 @@ import com.google.common.base.Objects;
 import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
-import org.jclouds.javax.annotation.Nullable;
-
-import java.beans.ConstructorProperties;
-import java.net.URI;
-import java.util.Date;
-
-import static com.google.common.base.Objects.ToStringHelper;
-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;
 
 /**
  * Base class for Google Compute Engine resources.
@@ -44,6 +45,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
 public class Resource {
 
    public enum Kind {
+      ADDRESS,
+      ADDRESS_LIST,
       DISK,
       DISK_LIST,
       FIREWALL,
@@ -61,6 +64,12 @@ public class Resource {
       PROJECT,
       NETWORK,
       NETWORK_LIST,
+      REGION,
+      REGION_LIST,
+      ROUTE,
+      ROUTE_LIST,
+      SNAPSHOT,
+      SNAPSHOT_LIST,
       ZONE,
       ZONE_LIST;
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Route.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Route.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Route.java
new file mode 100644
index 0000000..b15f986
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Route.java
@@ -0,0 +1,434 @@
+/*
+ * 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.Map;
+import java.util.Set;
+
+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 route resource.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/routes"/>
+ */
+@Beta
+public final class Route extends Resource {
+
+   private final URI network;
+   private final Set<String> tags;
+   private final String destRange;
+   private final Integer priority;
+   private final Optional<URI> nextHopInstance;
+   private final Optional<String> nextHopIp;
+   private final Optional<URI> nextHopNetwork;
+   private final Optional<URI> nextHopGateway;
+   private final Set<Warning> warnings;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "network", "tags",
+           "destRange", "priority", "nextHopInstance", "nextHopIp", "nextHopNetwork",
+           "nextHopGateway", "warnings"
+   })
+   private Route(String id, Date creationTimestamp, URI selfLink, String name, String description,
+                 URI network, Set<String> tags, String destRange, Integer priority,
+                 URI nextHopInstance, String nextHopIp, URI nextHopNetwork,
+                 URI nextHopGateway, Set<Warning> warnings) {
+      super(Kind.ROUTE, id, creationTimestamp, selfLink, name, description);
+      this.network = checkNotNull(network, "network for %name", name);
+      this.tags = tags == null ? ImmutableSet.<String>of() : tags;
+      this.destRange = checkNotNull(destRange, "destination range for %name", name);
+      this.priority = checkNotNull(priority, "priority of %name", name);
+      this.nextHopInstance = fromNullable(nextHopInstance);
+      this.nextHopIp = fromNullable(nextHopIp);
+      this.nextHopNetwork = fromNullable(nextHopNetwork);
+      this.nextHopGateway = fromNullable(nextHopGateway);
+      this.warnings = warnings == null ? ImmutableSet.<Warning>of() : warnings;
+   }
+
+   /**
+    * @return Network for this Route.
+    */
+   public URI getNetwork() {
+      return network;
+   }
+
+   /**
+    * @return The set of instance items to which this route applies.
+    */
+   public Set<String> getTags() {
+      return tags;
+   }
+
+   /**
+    * @return The destination range of outgoing packets that this route applies to.
+    */
+   public String getDestRange() {
+      return destRange;
+   }
+
+   /**
+    * @return The priority of this route. Priority is used to break ties in the case
+    *    where there is more than one matching route of maximum length. A lower value
+    *    is higher priority; a priority of 100 is higher than 200.
+    */
+   public Integer getPriority() {
+      return priority;
+   }
+
+   /**
+    * @return The fully-qualified URL to an instance that should handle matching packets.
+    */
+   public Optional<URI> getNextHopInstance() {
+      return nextHopInstance;
+   }
+
+   /**
+    * @return The network IP address of an instance that should handle matching packets.
+    */
+   public Optional<String> getNextHopIp() {
+      return nextHopIp;
+   }
+
+   /**
+    * @return The URL of the local network if it should handle matching packets.
+    */
+   public Optional<URI> getNextHopNetwork() {
+      return nextHopNetwork;
+   }
+
+   /**
+    * @return The URL to a gateway that should handle matching packets. Currently, this is only the internet gateway.
+    */
+   public Optional<URI> getNextHopGateway() {
+      return nextHopGateway;
+   }
+
+   /**
+    * @return If potential misconfigurations are detected for this route, this field will be populated with warning messages.
+    */
+   public Set<Warning> getWarnings() {
+      return warnings;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .add("network", network)
+              .add("tags", tags)
+              .add("destRange", destRange)
+              .add("priority", priority)
+              .add("nextHopInstance", nextHopInstance.orNull())
+              .add("nextHopIp", nextHopIp.orNull())
+              .add("nextHopNetwork", nextHopNetwork.orNull())
+              .add("nextHopGateway", nextHopGateway.orNull())
+              .add("warnings", warnings);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromRoute(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      private URI network;
+      private ImmutableSet.Builder<String> tags = ImmutableSet.builder();
+      private String destRange;
+      private Integer priority;
+      private URI nextHopInstance;
+      private String nextHopIp;
+      private URI nextHopNetwork;
+      private URI nextHopGateway;
+      private ImmutableSet.Builder<Warning> warnings = ImmutableSet.builder();
+
+
+      /**
+       * @see Route#getNetwork()
+       */
+      public Builder network(URI network) {
+         this.network = network;
+         return this;
+      }
+
+      /**
+       * @see Route#getTags()
+       */
+      public Builder addTag(String tag) {
+         this.tags.add(tag);
+         return this;
+      }
+
+      /**
+       * @see Route#getTags()
+       */
+      public Builder tags(Set<String> tags) {
+         this.tags.addAll(tags);
+         return this;
+      }
+
+      /**
+       * @see Route#getDestRange()
+       */
+      public Builder destRange(String destRange) {
+         this.destRange = destRange;
+         return this;
+      }
+
+      /**
+       * @see Route#getPriority()
+       */
+      public Builder priority(Integer priority) {
+         this.priority = priority;
+         return this;
+      }
+
+      /**
+       * @see Route#getNextHopInstance()
+       */
+      public Builder nextHopInstance(URI nextHopInstance) {
+         this.nextHopInstance = nextHopInstance;
+         return this;
+      }
+
+      /**
+       * @see Route#getNextHopIp()
+       */
+      public Builder nextHopIp(String nextHopIp) {
+         this.nextHopIp = nextHopIp;
+         return this;
+      }
+
+      /**
+       * @see Route#getNextHopNetwork()
+       */
+      public Builder nextHopNetwork(URI nextHopNetwork) {
+         this.nextHopNetwork = nextHopNetwork;
+         return this;
+      }
+
+      /**
+       * @see Route#getNextHopGateway()
+       */
+      public Builder nextHopGateway(URI nextHopGateway) {
+         this.nextHopGateway = nextHopGateway;
+         return this;
+      }
+
+      /**
+       * @see Route#getWarnings()
+       */
+      public Builder addWarning(Warning warning) {
+         this.warnings.add(warning);
+         return this;
+      }
+
+      /**
+       * @see Route#getWarnings()
+       */
+      public Builder warnings(Set<Warning> warnings) {
+         this.warnings.addAll(warnings);
+         return this;
+      }
+
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public Route build() {
+         return new Route(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, network, tags.build(), destRange, priority,
+                 nextHopInstance, nextHopIp, nextHopNetwork, nextHopGateway,
+                 warnings.build());
+      }
+
+      public Builder fromRoute(Route in) {
+         return super.fromResource(in)
+                 .network(in.getNetwork())
+                 .tags(in.getTags())
+                 .destRange(in.getDestRange())
+                 .priority(in.getPriority())
+                 .nextHopInstance(in.getNextHopInstance().orNull())
+                 .nextHopIp(in.getNextHopIp().orNull())
+                 .nextHopNetwork(in.getNextHopNetwork().orNull())
+                 .nextHopGateway(in.getNextHopGateway().orNull())
+                 .warnings(in.getWarnings());
+      }
+   }
+
+   /**
+    * If potential misconfigurations are detected for this route, this field will be populated with warning messages.
+    */
+   public static class Warning {
+      private final String code;
+      private final Optional<String> message;
+      private final Map<String, String> data;
+
+      @ConstructorProperties({
+              "code", "message", "data"
+      })
+      public Warning(String code, String message, Map<String, String> data) {
+         this.code = checkNotNull(code, "code");
+         this.message = fromNullable(message);
+         this.data = data == null ? ImmutableMap.<String, String>of() : data;
+      }
+
+      /**
+       * @return The warning type identifier for this warning.
+       */
+      public String getCode() {
+         return code;
+      }
+
+      /**
+       * @return Optional human-readable details for this warning.
+       */
+      public Optional<String> getMessage() {
+         return message;
+      }
+
+      /**
+       * @return Metadata for this warning
+       */
+      public Map<String, String> getData() {
+         return data;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(code, message, data);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj) return true;
+         if (obj == null || getClass() != obj.getClass()) return false;
+         Warning that = Warning.class.cast(obj);
+         return equal(this.code, that.code)
+                 && equal(this.message, that.message)
+                 && equal(this.data, that.data);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      protected Objects.ToStringHelper string() {
+         return toStringHelper(this)
+                 .add("code", code)
+                 .add("message", message)
+                 .add("data", data);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromWarning(this);
+      }
+
+      public static final class Builder {
+         private String code;
+         private String message;
+         private ImmutableMap.Builder<String, String> data = ImmutableMap.builder();
+
+         /**
+          * @see Warning#getCode()
+          */
+         public Builder code(String code) {
+            this.code = code;
+            return this;
+         }
+
+         /**
+          * @see Warning#getMessage()
+          */
+         public Builder message(String message) {
+            this.message = message;
+            return this;
+         }
+
+         /**
+          * @see Warning#getData()
+          */
+         public Builder data(Map<String, String> data) {
+            this.data = new ImmutableMap.Builder<String, String>().putAll(data);
+            return this;
+         }
+
+         /**
+          * @see Warning#getData()
+          */
+         public Builder addData(String key, String value) {
+            this.data.put(checkNotNull(key, "key"), checkNotNull(value, "value of %s", key));
+            return this;
+         }
+
+         public Warning build() {
+            return new Warning(code, message, data.build());
+         }
+
+         public Builder fromWarning(Warning in) {
+            return this.code(in.getCode())
+                    .message(in.getMessage().orNull())
+                    .data(in.getData());
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/SlashEncodedIds.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/SlashEncodedIds.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/SlashEncodedIds.java
new file mode 100644
index 0000000..72c1dc5
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/SlashEncodedIds.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Adam Lowe
+ */
+public class SlashEncodedIds {
+   public static SlashEncodedIds fromSlashEncoded(String id) {
+      Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+      checkArgument(Iterables.size(parts) == 2, "id must be in format firstId/secondId");
+      return new SlashEncodedIds(Iterables.get(parts, 0), Iterables.get(parts, 1));
+   }
+
+   public static SlashEncodedIds fromTwoIds(String firstId, String secondId) {
+      return new SlashEncodedIds(firstId, secondId);
+   }
+
+   private static String slashEncodeTwoIds(String firstId, String secondId) {
+      return checkNotNull(firstId, "firstId") + "/" + checkNotNull(secondId, "secondId");
+   }
+
+   public String slashEncode() {
+      return slashEncodeTwoIds(firstId, secondId);
+   }
+
+   protected final String firstId;
+   protected final String secondId;
+
+   protected SlashEncodedIds(String firstId, String secondId) {
+      this.firstId = checkNotNull(firstId, "firstId");
+      this.secondId = checkNotNull(secondId, "secondId");
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(firstId, secondId);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      SlashEncodedIds other = (SlashEncodedIds) obj;
+      return Objects.equal(firstId, other.firstId) && Objects.equal(secondId, other.secondId);
+   }
+
+   public String getFirstId() {
+      return firstId;
+   }
+
+   public String getSecondId() {
+      return secondId;
+   }
+
+   @Override
+   public String toString() {
+      return "[firstId=" + firstId + ", secondId=" + secondId + "]";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Snapshot.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Snapshot.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Snapshot.java
new file mode 100644
index 0000000..c487b7c
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Snapshot.java
@@ -0,0 +1,136 @@
+/*
+ * 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.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * A Persistent Disk Snapshot resource.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/snapshots"/>
+ */
+@Beta
+public final class Snapshot extends AbstractDisk {
+
+   private final Optional<URI> sourceDisk;
+   private final String sourceDiskId;
+
+   @ConstructorProperties({
+           "id", "creationTimestamp", "selfLink", "name", "description", "diskSizeGb",
+           "status", "sourceDisk", "sourceDiskId"
+   })
+   private Snapshot(String id, Date creationTimestamp, URI selfLink, String name, String description,
+                    Integer sizeGb, String status, URI sourceDisk, String sourceDiskId) {
+      super(Kind.SNAPSHOT, id, creationTimestamp, selfLink, name, description, sizeGb, status);
+      this.sourceDisk = fromNullable(sourceDisk);
+      this.sourceDiskId = checkNotNull(sourceDiskId, "sourceDiskId of %s", name);
+   }
+
+   /**
+    * @return The source disk used to create this snapshot. Once the source disk
+    *   has been deleted from the system, this field will be cleared, and will
+    *   not be set even if a disk with the same name has been re-created (output only).
+    */
+   public Optional<URI> getSourceDisk() {
+      return sourceDisk;
+   }
+
+   /**
+    * @return The ID value of the disk used to create this snapshot. This value
+    *   may be used to determine whether the snapshot was taken from the current
+    *   or a previous instance of a given disk name.
+    */
+   public String getSourceDiskId() {
+      return sourceDiskId;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected Objects.ToStringHelper string() {
+      return super.string()
+              .omitNullValues()
+              .add("sourceDisk", sourceDisk.orNull())
+              .add("sourceDiskId", sourceDiskId);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromSnapshot(this);
+   }
+
+   public static final class Builder extends AbstractDisk.Builder<Builder> {
+
+      private URI sourceDisk;
+      private String sourceDiskId;
+
+      /**
+       * @see Snapshot#getSourceDisk()
+       */
+      public Builder sourceDisk(URI sourceDisk) {
+         this.sourceDisk = sourceDisk;
+         return this;
+      }
+
+      /**
+       * @see Snapshot#getSourceDiskId()
+       */
+      public Builder sourceDiskId(String sourceDiskId) {
+         this.sourceDiskId = sourceDiskId;
+         return this;
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+
+      public Snapshot build() {
+         return new Snapshot(super.id, super.creationTimestamp, super.selfLink, super.name,
+                 super.description, super.sizeGb, super.status, sourceDisk, sourceDiskId);
+      }
+
+      public Builder fromSnapshot(Snapshot in) {
+         return super.fromAbstractDisk(in)
+                 .sourceDisk(in.getSourceDisk().orNull())
+                 .sourceDiskId(in.getSourceDiskId());
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Zone.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Zone.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Zone.java
index 2d41a74..254b83d 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Zone.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/domain/Zone.java
@@ -16,27 +16,28 @@
  */
 package org.jclouds.googlecomputeengine.domain;
 
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.javax.annotation.Nullable;
+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 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 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 zone resource.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/zones"/>
  */
 @Beta
 public final class Zone extends Resource {
@@ -181,7 +182,7 @@ public final class Zone extends Resource {
     * Scheduled maintenance windows for the zone. When the zone is in a maintenance window,
     * all resources which reside in the zone will be unavailable.
     *
-    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
+    * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/zones"/>
     */
    public static final class MaintenanceWindow {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AddressApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AddressApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AddressApi.java
new file mode 100644
index 0000000..795f150
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/AddressApi.java
@@ -0,0 +1,188 @@
+/*
+ * 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.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+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.Address;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.functions.internal.ParseAddresses;
+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.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * Provides access to Addresses via their REST API.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/addresses"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+public interface AddressApi {
+
+   /**
+    * Returns the specified address resource.
+    *
+    * @param region     Name of the region the address is in.
+    * @param addressName name of the address resource to return.
+    * @return a Address resource.
+    */
+   @Named("Addresss:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses/{address}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Address getInRegion(@PathParam("region") String region, @PathParam("address") String addressName);
+
+   /**
+    * Creates a address resource in the specified project specifying the size of the address.
+    *
+    *
+    * @param region     the name of the region where the address is to be created.
+    * @param addressName the name of address.
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Addresss:insert")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes({COMPUTE_SCOPE})
+   @MapBinder(BindToJsonPayload.class)
+   Operation createInRegion(@PathParam("region") String region, @PayloadParam("name") String addressName);
+
+   /**
+    * Deletes the specified address resource.
+    *
+    * @param region     the region the address is in.
+    * @param addressName name of the address resource to delete.
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Addresss:delete")
+   @DELETE
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses/{address}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation deleteInRegion(@PathParam("region") String region, @PathParam("address") String addressName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.AddressApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Addresss:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseAddresses.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Address> listFirstPageInRegion(@PathParam("region") String region);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.AddressApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Addresss:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseAddresses.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Address> listAtMarkerInRegion(@PathParam("region") String region, @QueryParam("pageToken") @Nullable String marker);
+
+   /**
+    * Retrieves the listPage of address resources contained within the specified project and region.
+    * By default the listPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has
+    * not been set.
+    *
+    * @param region        the region to search in
+    * @param marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the listPage
+    * @see org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("Addresss:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseAddresses.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Address> listAtMarkerInRegion(@PathParam("region") String region, @QueryParam("pageToken") @Nullable String marker, ListOptions listOptions);
+
+   /**
+    * A paged version of AddressApi#listPageInRegion(String)
+    *
+    * @param region the region to list in
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.collect.PagedIterable
+    * @see org.jclouds.googlecomputeengine.features.AddressApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Addresss:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseAddresses.class)
+   @Transform(ParseAddresses.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Address> listInRegion(@PathParam("region") String region);
+
+   @Named("Addresss:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/regions/{region}/addresses")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseAddresses.class)
+   @Transform(ParseAddresses.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Address> listInRegion(@PathParam("region") String region, ListOptions options);
+
+}


[04/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiExpectTest.java
index 3526efd..702f995 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiExpectTest.java
@@ -16,6 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseMachineTypeListTest;
 import org.jclouds.googlecomputeengine.parse.ParseMachineTypeTest;
@@ -23,11 +28,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.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 /**
  * @author David Alves
  */
@@ -37,7 +37,7 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
    public static final HttpRequest LIST_MACHINE_TYPES_REQUEST = HttpRequest
            .builder()
            .method("GET")
-           .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -46,12 +46,24 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
            .payload(staticPayloadFromResource("/machinetype_list.json"))
            .build();
 
+   public static final HttpRequest LIST_CENTRAL1B_MACHINE_TYPES_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b/machineTypes")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse LIST_CENTRAL1B_MACHINE_TYPES_RESPONSE = HttpResponse.builder()
+           .statusCode(200)
+           .payload(staticPayloadFromResource("/machinetype_list_central1b.json"))
+           .build();
+
    public void testGetMachineTypeResponseIs2xx() throws Exception {
       HttpRequest get = HttpRequest
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -61,7 +73,7 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
       MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, get, operationResponse).getMachineTypeApiForProject("myproject");
 
-      assertEquals(machineTypeApi.get("n1-standard-1"),
+      assertEquals(machineTypeApi.getInZone("us-central1-a", "n1-standard-1"),
               new ParseMachineTypeTest().expected());
    }
 
@@ -70,7 +82,7 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -79,7 +91,7 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
       MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, get, operationResponse).getMachineTypeApiForProject("myproject");
 
-      assertNull(machineTypeApi.get("n1-standard-1"));
+      assertNull(machineTypeApi.getInZone("us-central1-a", "n1-standard-1"));
    }
 
    public void testListMachineTypeNoOptionsResponseIs2xx() throws Exception {
@@ -88,7 +100,7 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
               TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE).getMachineTypeApiForProject
               ("myproject");
 
-      assertEquals(machineTypeApi.listFirstPage().toString(),
+      assertEquals(machineTypeApi.listFirstPageInZone("us-central1-a").toString(),
               new ParseMachineTypeListTest().expected().toString());
    }
 
@@ -99,6 +111,6 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTe
       MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
               TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, operationResponse).getMachineTypeApiForProject("myproject");
 
-      assertTrue(machineTypeApi.list().concat().isEmpty());
+      assertTrue(machineTypeApi.listInZone("us-central1-a").concat().isEmpty());
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiLiveTest.java
index 2a75366..af2b780 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/MachineTypeApiLiveTest.java
@@ -16,8 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.MachineType;
@@ -25,13 +31,8 @@ import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTe
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
-import java.util.Iterator;
-import java.util.List;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 /**
  * @author David Alves
@@ -47,7 +48,7 @@ public class MachineTypeApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live")
    public void testListMachineType() {
 
-      PagedIterable<MachineType> machineTypes = api().list(new ListOptions.Builder()
+      PagedIterable<MachineType> machineTypes = api().listInZone(DEFAULT_ZONE_NAME, new ListOptions.Builder()
               .maxResults(1));
 
       Iterator<IterableWithMarker<MachineType>> pageIterator = machineTypes.iterator();
@@ -64,7 +65,7 @@ public class MachineTypeApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
    @Test(groups = "live", dependsOnMethods = "testListMachineType")
    public void testGetMachineType() {
-      MachineType machineType = api().get(this.machineType.getName());
+      MachineType machineType = api().getInZone(DEFAULT_ZONE_NAME, this.machineType.getName());
       assertNotNull(machineType);
       assertMachineTypeEquals(machineType, this.machineType);
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiExpectTest.java
index 2b46e0a..0198644 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiExpectTest.java
@@ -16,6 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseNetworkListTest;
 import org.jclouds.googlecomputeengine.parse.ParseNetworkTest;
@@ -24,14 +32,6 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.core.MediaType;
-
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.AssertJUnit.assertNull;
-
 /**
  * @author David Alves
  */
@@ -41,7 +41,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
    public static final HttpRequest GET_NETWORK_REQUEST = HttpRequest
            .builder()
            .method("GET")
-           .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/jclouds-test")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -61,7 +61,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       HttpRequest get = HttpRequest
               .builder()
               .method("GET")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/jclouds-test")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -77,7 +77,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
       HttpRequest insert = HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(payloadFromResourceWithContentType("/network_insert.json", MediaType.APPLICATION_JSON))
@@ -98,7 +98,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
+                      ".com/compute/v1beta15/projects/myproject/global/networks/jclouds-test")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -117,7 +117,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
+                      ".com/compute/v1beta15/projects/myproject/global/networks/jclouds-test")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -134,7 +134,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks")
+                      ".com/compute/v1beta15/projects/myproject/global/networks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
@@ -153,7 +153,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks")
+                      ".com/compute/v1beta15/projects/myproject/global/networks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiLiveTest.java
index b8c676c..b826e5f 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/NetworkApiLiveTest.java
@@ -46,7 +46,7 @@ public class NetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live")
    public void testInsertNetwork() {
 
-      assertOperationDoneSucessfully(api().createInIPv4Range(NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().createInIPv4Range(NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
 
    }
 
@@ -75,7 +75,7 @@ public class NetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
    @Test(groups = "live", dependsOnMethods = "testListNetwork")
    public void testDeleteNetwork() {
 
-      assertOperationDoneSucessfully(api().delete(NETWORK_NAME), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().delete(NETWORK_NAME), TIME_WAIT);
    }
 
    private void assertNetworkEquals(Network result) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiExpectTest.java
deleted file mode 100644
index 7fefa48..0000000
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiExpectTest.java
+++ /dev/null
@@ -1,161 +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.features;
-
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
-import org.jclouds.googlecomputeengine.options.ListOptions;
-import org.jclouds.googlecomputeengine.parse.ParseOperationListTest;
-import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
-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.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-/**
- * @author David Alves
- */
-@Test(groups = "unit")
-public class OperationApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
-
-   private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
-           ".com/compute/v1beta13/projects/myproject/operations";
-
-   public static final HttpRequest GET_OPERATION_REQUEST = HttpRequest
-           .builder()
-           .method("GET")
-           .endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
-           .addHeader("Accept", "application/json")
-           .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-   public static final HttpResponse GET_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
-           .payload(staticPayloadFromResource("/operation.json")).build();
-
-   public void testGetOperationResponseIs2xx() throws Exception {
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, GET_OPERATION_REQUEST, GET_OPERATION_RESPONSE).getOperationApiForProject("myproject");
-
-      assertEquals(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"),
-              new ParseOperationTest().expected());
-   }
-
-   public void testGetOperationResponseIs4xx() throws Exception {
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, GET_OPERATION_REQUEST, operationResponse).getOperationApiForProject("myproject");
-
-      assertNull(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"));
-   }
-
-   public void testDeleteOperationResponseIs2xx() throws Exception {
-      HttpRequest delete = HttpRequest
-              .builder()
-              .method("DELETE")
-              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(204).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
-              TOKEN_RESPONSE, delete, operationResponse).getOperationApiForProject("myproject");
-
-      operationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
-   }
-
-   public void testDeleteOperationResponseIs4xx() throws Exception {
-      HttpRequest delete = HttpRequest
-              .builder()
-              .method("DELETE")
-              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
-              TOKEN_RESPONSE, delete, operationResponse).getOperationApiForProject("myproject");
-
-      operationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
-   }
-
-   public void testLisOperationWithNoOptionsResponseIs2xx() {
-      HttpRequest get = HttpRequest
-              .builder()
-              .method("GET")
-              .endpoint(OPERATIONS_URL_PREFIX)
-              .addHeader("Accept", "application/json")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation_list.json")).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
-
-      assertEquals(operationApi.listFirstPage().toString(),
-              new ParseOperationListTest().expected().toString());
-   }
-
-   public void testListOperationWithPaginationOptionsResponseIs2xx() {
-      HttpRequest get = HttpRequest
-              .builder()
-              .method("GET")
-              .endpoint(OPERATIONS_URL_PREFIX +
-                      "?pageToken=CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcG" +
-                      "VyYXRpb24tMTM1MjI0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz&" +
-                      "filter=" +
-                      "status%20eq%20done&" +
-                      "maxResults=3")
-              .addHeader("Accept", "application/json")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation_list.json")).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
-
-      assertEquals(operationApi.listAtMarker("CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcGVyYXRpb24tMTM1Mj" +
-              "I0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz",
-              new ListOptions.Builder().filter("status eq done").maxResults(3)).toString(),
-              new ParseOperationListTest().expected().toString());
-   }
-
-   public void testListOperationWithPaginationOptionsResponseIs4xx() {
-      HttpRequest get = HttpRequest
-              .builder()
-              .method("GET")
-              .endpoint(OPERATIONS_URL_PREFIX)
-              .addHeader("Accept", "application/json")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
-
-      OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
-
-      assertTrue(operationApi.list().concat().isEmpty());
-   }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiLiveTest.java
deleted file mode 100644
index 982a6ba..0000000
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/OperationApiLiveTest.java
+++ /dev/null
@@ -1,93 +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.features;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
-import org.jclouds.googlecomputeengine.options.ListOptions;
-import org.testng.annotations.Test;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.jclouds.googlecomputeengine.features.ProjectApiLiveTest.addItemToMetadata;
-import static org.jclouds.googlecomputeengine.features.ProjectApiLiveTest.deleteItemFromMetadata;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-/**
- * @author David Alves
- */
-public class OperationApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
-
-   private static final String METADATA_ITEM_KEY = "operationLiveTestTestProp";
-   private static final String METADATA_ITEM_VALUE = "operationLiveTestTestValue";
-   private Operation addOperation;
-   private Operation deleteOperation;
-
-   private OperationApi api() {
-      return api.getOperationApiForProject(userProject.get());
-   }
-
-
-   @Test(groups = "live")
-   public void testCreateOperations() {
-      //create some operations by adding and deleting metadata items
-      // this will make sure there is stuff to listFirstPage
-      addOperation = assertOperationDoneSucessfully(addItemToMetadata(api.getProjectApi(),
-              userProject.get(), METADATA_ITEM_KEY, METADATA_ITEM_VALUE), 20);
-      deleteOperation = assertOperationDoneSucessfully(deleteItemFromMetadata(api
-              .getProjectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
-
-      assertNotNull(addOperation);
-      assertNotNull(deleteOperation);
-   }
-
-   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
-   public void testGetOperation() {
-      Operation operation = api().get(addOperation.getName());
-      assertNotNull(operation);
-      assertOperationEquals(operation, this.addOperation);
-   }
-
-   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
-   public void testListOperationsWithFiltersAndPagination() {
-      PagedIterable<Operation> operations = api().list(new ListOptions.Builder()
-              .filter("operationType eq setMetadata")
-              .maxResults(1));
-
-      // make sure that in spite of having only one result per page we get at least two results
-      final AtomicInteger counter = new AtomicInteger();
-      operations.firstMatch(new Predicate<IterableWithMarker<Operation>>() {
-
-         @Override
-         public boolean apply(IterableWithMarker<Operation> input) {
-            counter.addAndGet(Iterables.size(input));
-            return counter.get() == 2;
-         }
-      });
-   }
-
-   private void assertOperationEquals(Operation result, Operation expected) {
-      assertEquals(result.getName(), expected.getName());
-   }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiExpectTest.java
index 83c8360..ad3fa6a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiExpectTest.java
@@ -16,7 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.GoogleComputeEngineConstants;
+import org.jclouds.googlecomputeengine.domain.Metadata;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseMetadataTest;
 import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
@@ -25,11 +31,6 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.core.MediaType;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-
 
 /**
  * @author David Alves
@@ -37,22 +38,22 @@ import static org.testng.Assert.assertNull;
 @Test(groups = "unit")
 public class ProjectApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
 
-   public static final String PROJECTS_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects";
+   public static final String PROJECTS_URL_PREFIX = "https://www.googleapis.com/compute/v1beta15/projects";
 
-   public void testGetProjectResponseIs2xx() throws Exception {
-      HttpRequest getProjectRequest = HttpRequest
-              .builder()
-              .method("GET")
-              .endpoint(PROJECTS_URL_PREFIX + "/myproject")
-              .addHeader("Accept", "application/json")
-              .addHeader("Authorization", "Bearer " + TOKEN).build();
+   public static final HttpRequest GET_PROJECT_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(PROJECTS_URL_PREFIX + "/myproject")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
 
-      HttpResponse getProjectResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/project.json")).build();
+   public static final HttpResponse GET_PROJECT_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/project.json")).build();
 
+   public void testGetProjectResponseIs2xx() throws Exception {
       ProjectApi api = requestsSendResponses(requestForScopes(GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE),
-              TOKEN_RESPONSE, getProjectRequest,
-              getProjectResponse).getProjectApi();
+              TOKEN_RESPONSE, GET_PROJECT_REQUEST,
+              GET_PROJECT_RESPONSE).getProjectApi();
 
       assertEquals(api.get("myproject"), new ParseProjectTest().expected());
    }
@@ -85,13 +86,13 @@ public class ProjectApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
               .build();
 
       HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
-              .payload(payloadFromResource("/operation.json")).build();
+              .payload(payloadFromResource("/global_operation.json")).build();
 
       ProjectApi api = requestsSendResponses(requestForScopes(GoogleComputeEngineConstants.COMPUTE_SCOPE),
               TOKEN_RESPONSE, setMetadata,
               setMetadataResponse).getProjectApi();
-
-      assertEquals(api.setCommonInstanceMetadata("myproject", new ParseMetadataTest().expected()),
+      Metadata expected = new ParseMetadataTest().expected();
+      assertEquals(api.setCommonInstanceMetadata("myproject", expected.getItems(), expected.getFingerprint()),
               new ParseOperationTest().expected());
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiLiveTest.java
index 7d24724..89a6100 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ProjectApiLiveTest.java
@@ -20,13 +20,6 @@ package org.jclouds.googlecomputeengine.features;
  * @author David Alves
  */
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import org.jclouds.googlecomputeengine.domain.Operation;
-import org.jclouds.googlecomputeengine.domain.Project;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
-import org.testng.annotations.Test;
-
 import static com.google.common.base.Predicates.equalTo;
 import static com.google.common.base.Predicates.not;
 import static org.testng.Assert.assertEquals;
@@ -36,6 +29,14 @@ import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Project;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
 /**
  * @author David Alves
  */
@@ -50,6 +51,7 @@ public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
    private Project project;
    private int initialMetadataSize;
+   private String initialFingerprint;
 
    @Test(groups = "live")
    public void testGetProjectWhenExists() {
@@ -67,24 +69,27 @@ public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
 
    @Test(groups = "live", dependsOnMethods = "testGetProjectWhenExists")
    public void addItemToMetadata() {
-      this.initialMetadataSize = project.getCommonInstanceMetadata().size();
-      assertOperationDoneSucessfully(addItemToMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY,
+      this.initialMetadataSize = project.getCommonInstanceMetadata().getItems().size();
+      this.initialFingerprint = this.project.getCommonInstanceMetadata().getFingerprint();
+      assertGlobalOperationDoneSucessfully(addItemToMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY,
               METADATA_ITEM_VALUE), 20);
       this.project = projectApi().get(userProject.get());
       assertNotNull(project);
-      assertTrue(this.project.getCommonInstanceMetadata().containsKey(METADATA_ITEM_KEY),
+      assertTrue(this.project.getCommonInstanceMetadata().getItems().containsKey(METADATA_ITEM_KEY),
               this.project.toString());
-      assertEquals(this.project.getCommonInstanceMetadata().get(METADATA_ITEM_KEY),
+      assertEquals(this.project.getCommonInstanceMetadata().getItems().get(METADATA_ITEM_KEY),
               METADATA_ITEM_VALUE);
+      assertNotNull(this.project.getCommonInstanceMetadata().getFingerprint());
    }
 
    @Test(groups = "live", dependsOnMethods = "addItemToMetadata")
    public void testDeleteItemFromMetadata() {
-      assertOperationDoneSucessfully(deleteItemFromMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
+      assertGlobalOperationDoneSucessfully(deleteItemFromMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
       this.project = projectApi().get(userProject.get());
       assertNotNull(project);
-      assertFalse(project.getCommonInstanceMetadata().containsKey(METADATA_ITEM_KEY));
-      assertSame(this.project.getCommonInstanceMetadata().size(), initialMetadataSize);
+      assertFalse(project.getCommonInstanceMetadata().getItems().containsKey(METADATA_ITEM_KEY));
+      assertSame(this.project.getCommonInstanceMetadata().getItems().size(), initialMetadataSize);
+      assertEquals(this.project.getCommonInstanceMetadata().getFingerprint(), initialFingerprint);
    }
 
    /**
@@ -97,9 +102,10 @@ public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
       Project project = projectApi.get(projectName);
       assertNotNull(project);
       ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
-      metadataBuilder.putAll(project.getCommonInstanceMetadata());
+      metadataBuilder.putAll(project.getCommonInstanceMetadata().getItems());
       metadataBuilder.put(key, value);
-      return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build());
+      return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build(),
+              project.getCommonInstanceMetadata().getFingerprint());
    }
 
    /**
@@ -112,8 +118,9 @@ public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
       Project project = projectApi.get(projectName);
       assertNotNull(project);
       ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
-      metadataBuilder.putAll(Maps.filterKeys(project.getCommonInstanceMetadata(), not(equalTo(key))));
-      return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build());
+      metadataBuilder.putAll(Maps.filterKeys(project.getCommonInstanceMetadata().getItems(), not(equalTo(key))));
+      return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build(),
+              project.getCommonInstanceMetadata().getFingerprint());
    }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiExpectTest.java
new file mode 100644
index 0000000..da575da
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiExpectTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.parse.ParseRegionListTest;
+import org.jclouds.googlecomputeengine.parse.ParseRegionTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class RegionApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   public static final String REGIONS_URL_PREFIX = "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions";
+
+   public static final HttpRequest GET_REGION_REQ = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(REGIONS_URL_PREFIX + "/us-central1")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpRequest LIST_REGIONS_REQ = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(REGIONS_URL_PREFIX)
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse LIST_REGIONS_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/region_list.json")).build();
+
+   public void testGetRegionResponseIs2xx() throws Exception {
+
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/region_get.json")).build();
+
+      RegionApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_REGION_REQ, operationResponse).getRegionApiForProject("myproject");
+
+      assertEquals(api.get("us-central1"),
+              new ParseRegionTest().expected());
+   }
+
+   public void testGetRegionResponseIs4xx() throws Exception {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RegionApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_REGION_REQ, operationResponse).getRegionApiForProject("myproject");
+
+      assertNull(api.get("us-central1"));
+   }
+
+   public void testListRegionNoOptionsResponseIs2xx() throws Exception {
+
+      RegionApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, LIST_REGIONS_REQ, LIST_REGIONS_RESPONSE).getRegionApiForProject("myproject");
+
+      assertEquals(api.listFirstPage().toString(),
+              new ParseRegionListTest().expected().toString());
+   }
+
+   public void testListRegionWithPaginationOptionsResponseIs4xx() {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RegionApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, LIST_REGIONS_REQ, operationResponse).getRegionApiForProject("myproject");
+
+      assertTrue(api.list().concat().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiLiveTest.java
new file mode 100644
index 0000000..0025668
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionApiLiveTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Region;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * @author Andrew Bayer
+ */
+public class RegionApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private Region region;
+
+   private RegionApi api() {
+      return api.getRegionApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testListRegion() {
+
+      PagedIterable<Region> regions = api().list(new ListOptions.Builder()
+              .maxResults(1));
+
+      Iterator<IterableWithMarker<Region>> pageIterator = regions.iterator();
+      assertTrue(pageIterator.hasNext());
+
+      IterableWithMarker<Region> singlePageIterator = pageIterator.next();
+      List<Region> regionAsList = Lists.newArrayList(singlePageIterator);
+
+      assertSame(regionAsList.size(), 1);
+
+      this.region = Iterables.getOnlyElement(regionAsList);
+   }
+
+
+   @Test(groups = "live", dependsOnMethods = "testListRegion")
+   public void testGetRegion() {
+      Region region = api().get(this.region.getName());
+      assertNotNull(region);
+      assertRegionEquals(region, this.region);
+   }
+
+   private void assertRegionEquals(Region result, Region expected) {
+      assertEquals(result.getName(), expected.getName());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiExpectTest.java
new file mode 100644
index 0000000..172fa56
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiExpectTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Resource;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class RegionOperationApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
+           ".com/compute/v1beta15/projects/myproject/regions/us-central1/operations";
+
+   private static final String DELETE_OPERATIONS_URL_PREFIX = "https://www.googleapis" +
+           ".com/compute/v1beta15/projects/myproject/regions/us-central1/operations";
+
+   public static final HttpRequest GET_OPERATION_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse GET_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/region_operation.json")).build();
+
+   private Operation expected() {
+      SimpleDateFormatDateService dateService = new SimpleDateFormatDateService();
+      return Operation.builder().id("13053095055850848306")
+              .selfLink(URI.create("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/operations/operation-1354084865060-4cf88735faeb8" +
+                      "-bbbb12cb"))
+              .name("operation-1354084865060-4cf88735faeb8-bbbb12cb")
+              .targetLink(URI.create("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-address"))
+              .targetId("13053094017547040099")
+              .status(Operation.Status.DONE)
+              .user("user@developer.gserviceaccount.com")
+              .progress(100)
+              .insertTime(dateService.iso8601DateParse("2012-11-28T06:41:05.060"))
+              .startTime(dateService.iso8601DateParse("2012-11-28T06:41:05.142"))
+              .endTime(dateService.iso8601DateParse("2012-11-28T06:41:06.142"))
+              .operationType("insert")
+              .region(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"))
+              .build();
+   }
+
+   private ListPage<Operation> expectedList() {
+      return ListPage.<Operation>builder()
+              .kind(Resource.Kind.OPERATION_LIST)
+              .id("projects/myproject/regions/us-central1/operations")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/operations"))
+              .addItem(expected())
+              .build();
+   }
+
+   public void testGetOperationResponseIs2xx() throws Exception {
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_OPERATION_REQUEST, GET_OPERATION_RESPONSE).getRegionOperationApiForProject("myproject");
+
+      assertEquals(regionOperationApi.getInRegion("us-central1", "operation-1354084865060-4cf88735faeb8-bbbb12cb"),
+              expected());
+   }
+
+   public void testGetOperationResponseIs4xx() throws Exception {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_OPERATION_REQUEST, operationResponse).getRegionOperationApiForProject("myproject");
+
+      assertNull(regionOperationApi.getInRegion("us-central1", "operation-1354084865060-4cf88735faeb8-bbbb12cb"));
+   }
+
+   public void testDeleteOperationResponseIs2xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(DELETE_OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(204).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getRegionOperationApiForProject("myproject");
+
+      regionOperationApi.deleteInRegion("us-central1", "operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testDeleteOperationResponseIs4xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(DELETE_OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getRegionOperationApiForProject("myproject");
+
+      regionOperationApi.deleteInRegion("us-central1", "operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testLisOperationWithNoOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/region_operation_list.json")).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getRegionOperationApiForProject("myproject");
+
+      assertEquals(regionOperationApi.listFirstPageInRegion("us-central1").toString(),
+              expectedList().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX +
+                      "?pageToken=CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcG" +
+                      "VyYXRpb24tMTM1MjI0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz&" +
+                      "filter=" +
+                      "status%20eq%20done&" +
+                      "maxResults=3")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/region_operation_list.json")).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getRegionOperationApiForProject("myproject");
+
+      assertEquals(regionOperationApi.listAtMarkerInRegion("us-central1", "CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcGVyYXRpb24tMTM1Mj" +
+              "I0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz",
+              new ListOptions.Builder().filter("status eq done").maxResults(3)).toString(),
+              expectedList().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs4xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RegionOperationApi regionOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getRegionOperationApiForProject("myproject");
+
+      assertTrue(regionOperationApi.listInRegion("us-central1").concat().isEmpty());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiLiveTest.java
new file mode 100644
index 0000000..741141d
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RegionOperationApiLiveTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Andrew Bayer
+ */
+public class RegionOperationApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String ADDRESS_NAME = "region-operations-api-live-test-address";
+   private Operation addOperation;
+   private Operation deleteOperation;
+
+   private RegionOperationApi api() {
+      return api.getRegionOperationApiForProject(userProject.get());
+   }
+
+   private AddressApi addressApi() {
+      return api.getAddressApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testCreateOperations() {
+      //create some operations by adding and deleting metadata items
+      // this will make sure there is stuff to listFirstPage
+      addOperation = assertRegionOperationDoneSucessfully(addressApi().createInRegion(DEFAULT_REGION_NAME,
+              ADDRESS_NAME), 20);
+      deleteOperation = assertRegionOperationDoneSucessfully(addressApi().deleteInRegion(DEFAULT_REGION_NAME,
+              ADDRESS_NAME), 20);
+
+      assertNotNull(addOperation);
+      assertNotNull(deleteOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testGetOperation() {
+      Operation operation = api().getInRegion(DEFAULT_REGION_NAME, addOperation.getName());
+      assertNotNull(operation);
+      assertOperationEquals(operation, this.addOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testListOperationsWithFiltersAndPagination() {
+      PagedIterable<Operation> operations = api().listInRegion(DEFAULT_REGION_NAME, new ListOptions.Builder()
+//              .filter("operationType eq insert")
+              .maxResults(1));
+
+      // make sure that in spite of having only one result per page we get at least two results
+      final AtomicInteger counter = new AtomicInteger();
+      operations.firstMatch(new Predicate<IterableWithMarker<Operation>>() {
+
+         @Override
+         public boolean apply(IterableWithMarker<Operation> input) {
+            counter.addAndGet(Iterables.size(input));
+            return counter.get() == 2;
+         }
+      });
+   }
+
+   private void assertOperationEquals(Operation result, Operation expected) {
+      assertEquals(result.getName(), expected.getName());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiExpectTest.java
new file mode 100644
index 0000000..858d018
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiExpectTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
+import org.jclouds.googlecomputeengine.parse.ParseRouteListTest;
+import org.jclouds.googlecomputeengine.parse.ParseRouteTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class RouteApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   public void testGetRouteResponseIs2xx() throws Exception {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/route_get.json")).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getRouteApiForProject("myproject");
+
+      assertEquals(api.get("default-route-c99ebfbed0e1f375"),
+              new ParseRouteTest().expected());
+   }
+
+   public void testGetRouteResponseIs4xx() throws Exception {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getRouteApiForProject("myproject");
+
+      assertNull(api.get("default-route-c99ebfbed0e1f375"));
+   }
+
+   public void testInsertRouteResponseIs2xx() {
+      HttpRequest insert = HttpRequest
+              .builder()
+
+              .method("POST")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/route_insert.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse insertRouteResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/global_operation.json")).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, insert,
+              insertRouteResponse).getRouteApiForProject("myproject");
+
+      assertEquals(api.createInNetwork("default-route-c99ebfbed0e1f375",
+              URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"),
+              new RouteOptions().addTag("fooTag")
+                      .addTag("barTag")
+                      .description("Default route to the virtual network.")
+              .destRange("10.240.0.0/16")
+              .priority(1000)
+              .nextHopNetwork(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"))
+      ), new ParseOperationTest().expected());
+   }
+
+   public void testDeleteRouteResponseIs2xx() {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/global_operation.json")).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, deleteResponse).getRouteApiForProject("myproject");
+
+      assertEquals(api.delete("default-route-c99ebfbed0e1f375"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testDeleteRouteResponseIs4xx() {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, deleteResponse).getRouteApiForProject("myproject");
+
+      assertNull(api.delete("default-route-c99ebfbed0e1f375"));
+   }
+
+   public void testListRoutesResponseIs2xx() {
+      HttpRequest list = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/global/routes")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/route_list.json")).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, list, operationResponse).getRouteApiForProject("myproject");
+
+      assertEquals(api.listFirstPage().toString(),
+              new ParseRouteListTest().expected().toString());
+   }
+
+   public void testListRoutesResponseIs4xx() {
+      HttpRequest list = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/global/routes")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      RouteApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, list, operationResponse).getRouteApiForProject("myproject");
+
+      assertTrue(api.list().concat().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiLiveTest.java
new file mode 100644
index 0000000..48c4cf1
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/RouteApiLiveTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Route;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * @author Andrew Bayer
+ */
+public class RouteApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String DEST_RANGE = "20.10.0.0/16";
+   private static final String IPV4_RANGE = "10.0.0.0/8";
+   private static final String ROUTE_NAME = "route-api-live-test-route";
+   private static final String ROUTE_NETWORK_NAME = "route-api-live-test-network";
+   public static final int TIME_WAIT = 30;
+
+   private RouteApi api() {
+      return api.getRouteApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testInsertRoute() {
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
+              (ROUTE_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().createInNetwork(ROUTE_NAME,
+              getNetworkUrl(userProject.get(), ROUTE_NETWORK_NAME),
+              new RouteOptions().addTag("footag")
+                      .addTag("bartag")
+                      .description("RouteApi Live Test")
+                      .destRange(DEST_RANGE)
+                      .priority(1000)
+                      .nextHopGateway(getGatewayUrl(userProject.get(), DEFAULT_GATEWAY_NAME))),
+              TIME_WAIT);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testInsertRoute")
+   public void testGetRoute() {
+      Route route = api().get(ROUTE_NAME);
+
+      assertNotNull(route);
+      assertRouteEquals(route);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testGetRoute")
+   public void testListRoute() {
+
+      PagedIterable<Route> routes = api().list(new ListOptions()
+              .filter("name eq " + ROUTE_NAME));
+
+      List<Route> routesAsList = Lists.newArrayList(routes.concat());
+
+      assertEquals(routesAsList.size(), 1);
+
+      assertRouteEquals(Iterables.getOnlyElement(routesAsList));
+
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testListRoute")
+   public void testDeleteRoute() {
+      assertGlobalOperationDoneSucessfully(api().delete(ROUTE_NAME), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get())
+              .delete(ROUTE_NETWORK_NAME), TIME_WAIT);
+   }
+
+   private void assertRouteEquals(Route result) {
+      assertEquals(result.getName(), ROUTE_NAME);
+      assertEquals(result.getDestRange(), DEST_RANGE);
+      assertEquals(result.getNextHopGateway().orNull(), getGatewayUrl(userProject.get(), DEFAULT_GATEWAY_NAME));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiExpectTest.java
new file mode 100644
index 0000000..bc7d3b8
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiExpectTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.parse.ParseSnapshotListTest;
+import org.jclouds.googlecomputeengine.parse.ParseSnapshotTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class SnapshotApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   public static final String SNAPSHOT_URL_PREFIX = "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots";
+
+   public static final HttpRequest GET_SNAPSHOT_REQ = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(SNAPSHOT_URL_PREFIX + "/test-snap")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpRequest LIST_SNAPSHOTS_REQ = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(SNAPSHOT_URL_PREFIX)
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse LIST_SNAPSHOTS_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/snapshot_list.json")).build();
+
+   public void testGetSnapshotResponseIs2xx() throws Exception {
+
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/snapshot_get.json")).build();
+
+      SnapshotApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_SNAPSHOT_REQ, operationResponse).getSnapshotApiForProject("myproject");
+
+      assertEquals(api.get("test-snap"),
+              new ParseSnapshotTest().expected());
+   }
+
+   public void testGetSnapshotResponseIs4xx() throws Exception {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      SnapshotApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_SNAPSHOT_REQ, operationResponse).getSnapshotApiForProject("myproject");
+
+      assertNull(api.get("test-snap"));
+   }
+
+   public void testListSnapshotNoOptionsResponseIs2xx() throws Exception {
+
+      SnapshotApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, LIST_SNAPSHOTS_REQ, LIST_SNAPSHOTS_RESPONSE).getSnapshotApiForProject("myproject");
+
+      assertEquals(api.listFirstPage().toString(),
+              new ParseSnapshotListTest().expected().toString());
+   }
+
+   public void testListSnapshotWithPaginationOptionsResponseIs4xx() {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      SnapshotApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, LIST_SNAPSHOTS_REQ, operationResponse).getSnapshotApiForProject("myproject");
+
+      assertTrue(api.list().concat().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiLiveTest.java
new file mode 100644
index 0000000..519aeeb
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/SnapshotApiLiveTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.features;
+
+import static org.jclouds.googlecomputeengine.features.DiskApiLiveTest.TIME_WAIT;
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Disk;
+import org.jclouds.googlecomputeengine.domain.Snapshot;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * @author Andrew Bayer
+ */
+public class SnapshotApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String DISK_NAME = "snapshot-api-live-test-disk";
+   private static final String SNAPSHOT_NAME = "snapshot-api-live-test-snapshot";
+
+   private Disk disk;
+   private SnapshotApi api() {
+      return api.getSnapshotApiForProject(userProject.get());
+   }
+
+   private DiskApi diskApi() {
+      return api.getDiskApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testCreateSnapshot() {
+      assertZoneOperationDoneSucessfully(diskApi().createInZone(DISK_NAME, 1, DEFAULT_ZONE_NAME), TIME_WAIT);
+      disk = diskApi().getInZone(DEFAULT_ZONE_NAME, DISK_NAME);
+
+      assertZoneOperationDoneSucessfully(diskApi().createSnapshotInZone(DEFAULT_ZONE_NAME, DISK_NAME, SNAPSHOT_NAME),
+              TIME_WAIT);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateSnapshot")
+   public void testGetSnapshot() {
+      Snapshot snapshot = api().get(SNAPSHOT_NAME);
+
+      assertEquals(snapshot.getName(), SNAPSHOT_NAME);
+      assertSnapshotEquals(snapshot);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testGetSnapshot")
+   public void testListSnapshot() {
+
+      PagedIterable<Snapshot> snapshots = api().list(new ListOptions.Builder()
+              .filter("name eq " + SNAPSHOT_NAME));
+
+      List<Snapshot> snapshotsAsList = Lists.newArrayList(snapshots.concat());
+
+      assertEquals(snapshotsAsList.size(), 1);
+
+      assertSnapshotEquals(Iterables.getOnlyElement(snapshotsAsList));
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testListSnapshot")
+   public void testDeleteDisk() {
+
+      assertZoneOperationDoneSucessfully(diskApi().deleteInZone(DEFAULT_ZONE_NAME, DISK_NAME), TIME_WAIT);
+      assertGlobalOperationDoneSucessfully(api().delete(SNAPSHOT_NAME), TIME_WAIT);
+   }
+
+   private void assertSnapshotEquals(Snapshot result) {
+      assertEquals(result.getName(), SNAPSHOT_NAME);
+      assertEquals(result.getSourceDisk().orNull(), disk.getSelfLink());
+      assertEquals(result.getSizeGb(), disk.getSizeGb());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiExpectTest.java
index 9cd516c..aecfcab 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiExpectTest.java
@@ -16,6 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
 import org.jclouds.googlecomputeengine.parse.ParseZoneListTest;
 import org.jclouds.googlecomputeengine.parse.ParseZoneTest;
@@ -23,18 +28,13 @@ 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.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 /**
  * @author David Alves
  */
 @Test(groups = "unit")
 public class ZoneApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
 
-   public static final String ZONES_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones";
+   public static final String ZONES_URL_PREFIX = "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones";
 
    public static final HttpRequest GET_ZONE_REQ = HttpRequest
            .builder()
@@ -50,10 +50,12 @@ public class ZoneApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN).build();
 
+   public static final HttpResponse LIST_ZONES_SHORT_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/zone_list_short.json")).build();
+
    public static final HttpResponse LIST_ZONES_RESPONSE = HttpResponse.builder().statusCode(200)
            .payload(staticPayloadFromResource("/zone_list.json")).build();
 
-
    public void testGetZoneResponseIs2xx() throws Exception {
 
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiLiveTest.java
index 73fd9ec..612ba8d 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneApiLiveTest.java
@@ -16,8 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.features;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.List;
+
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.googlecomputeengine.domain.Zone;
@@ -25,13 +31,8 @@ import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTe
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.testng.annotations.Test;
 
-import java.util.Iterator;
-import java.util.List;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 
 /**
  * @author David Alves


[08/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/DiskApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/DiskApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/DiskApi.java
index faa05d1..b771c74 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/DiskApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/DiskApi.java
@@ -19,8 +19,6 @@ package org.jclouds.googlecomputeengine.features;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
 
-import java.net.URI;
-
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -57,7 +55,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
  * Provides access to Disks via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/disks"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/disks"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -66,25 +64,25 @@ public interface DiskApi {
    /**
     * Returns the specified persistent disk resource.
     *
+    * @param zone     Name of the zone the disk is in.
     * @param diskName name of the persistent disk resource to return.
     * @return a Disk resource.
     */
    @Named("Disks:get")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks/{disk}")
+   @Path("/zones/{zone}/disks/{disk}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Disk get(@PathParam("disk") String diskName);
+   Disk getInZone(@PathParam("zone") String zone, @PathParam("disk") String diskName);
 
    /**
     * Creates a persistent disk resource in the specified project specifying the size of the disk.
     *
-    *
     * @param diskName the name of disk.
     * @param sizeGb   the size of the disk
-    * @param zone     the URi of the zone where the disk is to be created.
+    * @param zone     the name of the zone where the disk is to be created.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
     */
@@ -92,16 +90,17 @@ public interface DiskApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes({COMPUTE_SCOPE})
    @MapBinder(BindToJsonPayload.class)
    Operation createInZone(@PayloadParam("name") String diskName,
-                                            @PayloadParam("sizeGb") int sizeGb,
-                                            @PayloadParam("zone") URI zone);
+                          @PayloadParam("sizeGb") int sizeGb,
+                          @PathParam("zone") String zone);
 
    /**
     * Deletes the specified persistent disk resource.
     *
+    * @param zone     the zone the disk is in.
     * @param diskName name of the persistent disk resource to delete.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
@@ -109,41 +108,42 @@ public interface DiskApi {
    @Named("Disks:delete")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks/{disk}")
+   @Path("/zones/{zone}/disks/{disk}")
    @OAuthScopes(COMPUTE_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Operation delete(@PathParam("disk") String diskName);
+   Operation deleteInZone(@PathParam("zone") String zone, @PathParam("disk") String diskName);
 
    /**
-    * @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see DiskApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Disks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseDisks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Disk> listFirstPage();
+   ListPage<Disk> listFirstPageInZone(@PathParam("zone") String zone);
 
    /**
-    * @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see DiskApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Disks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseDisks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Disk> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
+   ListPage<Disk> listAtMarkerInZone(@PathParam("zone") String zone, @QueryParam("pageToken") @Nullable String marker);
 
    /**
-    * Retrieves the listPage of persistent disk resources contained within the specified project.
+    * Retrieves the listPage of persistent disk resources contained within the specified project and zone.
     * By default the listPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has
     * not been set.
     *
+    * @param zone        the zone to search in
     * @param marker      marks the beginning of the next list page
     * @param listOptions listing options
     * @return a page of the listPage
@@ -153,36 +153,60 @@ public interface DiskApi {
    @Named("Disks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseDisks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Disk> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
+   ListPage<Disk> listAtMarkerInZone(@PathParam("zone") String zone, @QueryParam("pageToken") @Nullable String marker, ListOptions listOptions);
 
    /**
-    * A paged version of DiskApi#listPage()
+    * A paged version of DiskApi#listPageInZone(String)
     *
+    * @param zone the zone to list in
     * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
     * @see PagedIterable
-    * @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see DiskApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Disks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseDisks.class)
    @Transform(ParseDisks.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Disk> list();
+   PagedIterable<Disk> listInZone(@PathParam("zone") String zone);
 
    @Named("Disks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/disks")
+   @Path("/zones/{zone}/disks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseDisks.class)
    @Transform(ParseDisks.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Disk> list(ListOptions options);
+   PagedIterable<Disk> listInZone(@PathParam("zone") String zone, ListOptions options);
+
+   /**
+    * Create a snapshot of a given disk in a zone.
+    *
+    * @param zone the zone the disk is in.
+    * @param diskName the name of the disk.
+    * @param snapshotName the name for the snapshot to be craeted.
+    *
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Disks:createSnapshot")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/zones/{zone}/disks/{disk}/createSnapshot")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @MapBinder(BindToJsonPayload.class)
+   @Nullable
+   Operation createSnapshotInZone(@PathParam("zone") String zone,
+                                  @PathParam("disk") String diskName,
+                                  @PayloadParam("name") String snapshotName);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/FirewallApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/FirewallApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/FirewallApi.java
index 5a7a875..0c25b5b 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/FirewallApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/FirewallApi.java
@@ -63,7 +63,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
  * <p/>
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/firewalls"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -77,7 +77,7 @@ public interface FirewallApi {
    @Named("Firewalls:get")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls/{firewall}")
+   @Path("/global/firewalls/{firewall}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
@@ -86,8 +86,8 @@ public interface FirewallApi {
    /**
     * Creates a firewall resource in the specified project using the data included in the request.
     *
-    * @param name the name of the firewall to be inserted.
-    * @param network the network to which to add the firewall
+    * @param name            the name of the firewall to be inserted.
+    * @param network         the network to which to add the firewall
     * @param firewallOptions the options of the firewall to add
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
@@ -96,7 +96,7 @@ public interface FirewallApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes({COMPUTE_SCOPE})
    @MapBinder(FirewallBinder.class)
    Operation createInNetwork(@PayloadParam("name") String name,
@@ -106,8 +106,8 @@ public interface FirewallApi {
    /**
     * Updates the specified firewall resource with the data included in the request.
     *
-    * @param firewallName the name firewall to be updated.
-    * @param firewallOptions     the new firewall.
+    * @param firewallName    the name firewall to be updated.
+    * @param firewallOptions the new firewall.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
     */
@@ -115,7 +115,7 @@ public interface FirewallApi {
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/firewalls/{firewall}")
+   @Path("/global/firewalls/{firewall}")
    @OAuthScopes({COMPUTE_SCOPE})
    Operation update(@PathParam("firewall") String firewallName,
                     @BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
@@ -123,8 +123,8 @@ public interface FirewallApi {
    /**
     * Updates the specified firewall resource, with patch semantics, with the data included in the request.
     *
-    * @param firewallName the name firewall to be updated.
-    * @param firewallOptions     the new firewall.
+    * @param firewallName    the name firewall to be updated.
+    * @param firewallOptions the new firewall.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
     */
@@ -132,7 +132,7 @@ public interface FirewallApi {
    @PATCH
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/firewalls/{firewall}")
+   @Path("/global/firewalls/{firewall}")
    @OAuthScopes({COMPUTE_SCOPE})
    Operation patch(@PathParam("firewall") String firewallName,
                    @BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
@@ -140,14 +140,14 @@ public interface FirewallApi {
    /**
     * Deletes the specified image resource.
     *
-    * @param imageName name of the firewall resource to delete.
+    * @param firewallName name of the firewall resource to delete.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.  If the image did not exist the result is null.
     */
    @Named("Firewalls:delete")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls/{firewall}")
+   @Path("/global/firewalls/{firewall}")
    @OAuthScopes(COMPUTE_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    Operation delete(@PathParam("firewall") String firewallName);
@@ -158,7 +158,7 @@ public interface FirewallApi {
    @Named("Firewalls:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseFirewalls.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -170,7 +170,7 @@ public interface FirewallApi {
    @Named("Firewalls:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseFirewalls.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -190,7 +190,7 @@ public interface FirewallApi {
    @Named("Firewalls:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseFirewalls.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -202,7 +202,7 @@ public interface FirewallApi {
    @Named("Firewalls:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseFirewalls.class)
    @Transform(ParseFirewalls.ToPagedIterable.class)
@@ -219,7 +219,7 @@ public interface FirewallApi {
    @Named("Firewalls:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/firewalls")
+   @Path("/global/firewalls")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseFirewalls.class)
    @Transform(ParseFirewalls.ToPagedIterable.class)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/GlobalOperationApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/GlobalOperationApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/GlobalOperationApi.java
new file mode 100644
index 0000000..0b1b4d1
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/GlobalOperationApi.java
@@ -0,0 +1,159 @@
+/*
+ * 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.ParseGlobalOperations;
+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 Global Operations via their REST API.
+ *
+ * @author David Alves
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/globalOperations"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+public interface GlobalOperationApi {
+
+   /**
+    * Retrieves the specified operation resource.
+    *
+    * @param operationName name of the operation resource to return.
+    * @return If successful, this method returns an Operation resource
+    */
+   @Named("GlobalOperations:get")
+   @GET
+   @Path("/global/operations/{operation}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   Operation get(@PathParam("operation") String operationName);
+
+   /**
+    * Deletes the specified operation resource.
+    *
+    * @param operationName name of the operation resource to delete.
+    */
+   @Named("GlobalOperations:delete")
+   @DELETE
+   @Path("/global/operations/{operation}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   void delete(@PathParam("operation") String operationName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.GlobalOperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("GlobalOperations:list")
+   @GET
+   @Path("/global/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGlobalOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listFirstPage();
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.GlobalOperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("GlobalOperations:list")
+   @GET
+   @Path("/global/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGlobalOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarker(@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 marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the list, starting at marker
+    * @see org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("GlobalOperations:list")
+   @GET
+   @Path("/global/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGlobalOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
+                                    ListOptions listOptions);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.GlobalOperationApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("GlobalOperations:list")
+   @GET
+   @Path("/global/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGlobalOperations.class)
+   @Transform(ParseGlobalOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> list();
+
+   /**
+    * A paged version of GlobalOperationApi#listFirstPage()
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.collect.PagedIterable
+    * @see org.jclouds.googlecomputeengine.features.GlobalOperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("GlobalOperations:list")
+   @GET
+   @Path("/global/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseGlobalOperations.class)
+   @Transform(ParseGlobalOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> list(ListOptions listOptions);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ImageApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ImageApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ImageApi.java
index 74faa02..d3475e8 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ImageApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ImageApi.java
@@ -51,7 +51,7 @@ import org.jclouds.rest.annotations.Transform;
  * <p/>
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/images"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -65,7 +65,7 @@ public interface ImageApi {
    @Named("Images:get")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images/{image}")
+   @Path("/global/images/{image}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
@@ -81,7 +81,7 @@ public interface ImageApi {
    @Named("Images:delete")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images/{image}")
+   @Path("/global/images/{image}")
    @OAuthScopes(COMPUTE_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
@@ -93,7 +93,7 @@ public interface ImageApi {
    @Named("Images:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images")
+   @Path("/global/images")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseImages.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -105,7 +105,7 @@ public interface ImageApi {
    @Named("Images:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images")
+   @Path("/global/images")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseImages.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -116,7 +116,6 @@ public interface ImageApi {
     * By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
     * been set.
     *
-    *
     * @param marker      marks the beginning of the next list page
     * @param listOptions listing options
     * @return a page of the list
@@ -126,11 +125,11 @@ public interface ImageApi {
    @Named("Images:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images")
+   @Path("/global/images")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseImages.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Image> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
+   ListPage<Image> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions listOptions);
 
    /**
     * A paged version of ImageApi#list()
@@ -142,7 +141,7 @@ public interface ImageApi {
    @Named("Images:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images")
+   @Path("/global/images")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseImages.class)
    @Transform(ParseImages.ToPagedIterable.class)
@@ -159,10 +158,11 @@ public interface ImageApi {
    @Named("Images:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/images")
+   @Path("/global/images")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseImages.class)
    @Transform(ParseImages.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<Image> list(ListOptions options);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
index c78d3da..7d123a6 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/InstanceApi.java
@@ -19,6 +19,9 @@ package org.jclouds.googlecomputeengine.features;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
 
+import java.util.Map;
+import java.util.Set;
+
 import javax.inject.Named;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -40,6 +43,8 @@ import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Operation;
 import org.jclouds.googlecomputeengine.functions.internal.ParseInstances;
 import org.jclouds.googlecomputeengine.handlers.InstanceBinder;
+import org.jclouds.googlecomputeengine.handlers.MetadataBinder;
+import org.jclouds.googlecomputeengine.options.AttachDiskOptions;
 import org.jclouds.googlecomputeengine.options.ListOptions;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.oauth.v2.config.OAuthScopes;
@@ -58,7 +63,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
  * Provides access to Instances via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/instances"/>
  * @see InstanceApi
  */
 @SkipEncoding({'/', '='})
@@ -68,24 +73,26 @@ public interface InstanceApi {
    /**
     * Returns the specified instance resource.
     *
+    * @param zone zone the instance is in.
     * @param instanceName name of the instance resource to return.
     * @return an Instance resource
     */
    @Named("Instances:get")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances/{instance}")
+   @Path("/zones/{zone}/instances/{instance}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Instance get(@PathParam("instance") String instanceName);
+   Instance getInZone(@PathParam("zone") String zone, @PathParam("instance") String instanceName);
 
    /**
     * Creates a instance resource in the specified project using the data included in the request.
     *
+    *
     * @param instanceName this name of the instance to be created
-    * @param template the instance template
     * @param zone the name of the zone where the instance will be created
+    * @param template the instance template
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.
     */
@@ -93,16 +100,17 @@ public interface InstanceApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes({COMPUTE_SCOPE})
    @MapBinder(InstanceBinder.class)
-   Operation createInZone(@PayloadParam("name") String instanceName,
-                          @PayloadParam("template") InstanceTemplate template,
-                          @PayloadParam("zone") String zone);
+   Operation createInZone(@PayloadParam("name") String instanceName, @PathParam("zone") String zone,
+                          @PayloadParam("template") InstanceTemplate template);
+                          
 
    /**
     * Deletes the specified instance resource.
     *
+    * @param zone the instance is in.
     * @param instanceName name of the instance resource to delete.
     * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
     *         you, and look for the status field.  If the instance did not exist the result is null.
@@ -110,33 +118,35 @@ public interface InstanceApi {
    @Named("Instances:delete")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances/{instance}")
+   @Path("/zones/{zone}/instances/{instance}")
    @OAuthScopes(COMPUTE_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Operation delete(@PathParam("instance") String instanceName);
+   Operation deleteInZone(@PathParam("zone") String zone, @PathParam("instance") String instanceName);
 
    /**
-    * A paged version of InstanceApi#list()
+    * A paged version of InstanceApi#listInZone()
     *
+    * @param zone zone instances are in
     * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
     * @see PagedIterable
-    * @see InstanceApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see InstanceApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Instances:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseInstances.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Instance> listFirstPage();
+   ListPage<Instance> listFirstPageInZone(@PathParam("zone") String zone);
 
    /**
     * Retrieves the list of instance resources available to the specified project.
     * By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
     * been set.
     *
+    * @param zone zone instances are in
     * @param marker      marks the beginning of the next list page
     * @param listOptions listing options
     * @return a page of the list
@@ -146,53 +156,56 @@ public interface InstanceApi {
    @Named("Instances:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseInstances.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Instance> listAtMarker(@Nullable String marker);
+   ListPage<Instance> listAtMarkerInZone(@PathParam("zone") String zone, @Nullable String marker,
+                                         ListOptions listOptions);
 
    /**
-    * @see InstanceApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see InstanceApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Instances:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseInstances.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Instance> listAtMarker(@Nullable String marker, ListOptions options);
+   ListPage<Instance> listAtMarkerInZone(@PathParam("zone") String zone,
+                                         @Nullable String marker);
 
    /**
-    * @see InstanceApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see InstanceApi#listInZone(String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Instances:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseInstances.class)
    @Transform(ParseInstances.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Instance> list();
+   PagedIterable<Instance> listInZone(@PathParam("zone") String zone);
 
    /**
-    * @see InstanceApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see InstanceApi#listInZone(String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Instances:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances")
+   @Path("/zones/{zone}/instances")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseInstances.class)
    @Transform(ParseInstances.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Instance> list(ListOptions options);
+   PagedIterable<Instance> listInZone(@PathParam("zone") String zone, ListOptions options);
 
    /**
     * Adds an access config to an instance's network interface.
     *
+    * @param zone zone instance is in
     * @param instanceName         the instance name.
     * @param accessConfig         the AccessConfig to add.
     * @param networkInterfaceName network interface name.
@@ -203,16 +216,18 @@ public interface InstanceApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/instances/{instance}/addAccessConfig")
+   @Path("/zones/{zone}/instances/{instance}/addAccessConfig")
    @OAuthScopes({COMPUTE_SCOPE})
-   Operation addAccessConfigToNic(@PathParam("instance") String instanceName,
-                                  @BinderParam(BindToJsonPayload.class)
-                                  Instance.NetworkInterface.AccessConfig accessConfig,
-                                  @QueryParam("network_interface") String networkInterfaceName);
-
+   Operation addAccessConfigToNicInZone(@PathParam("zone") String zone,
+                                        @PathParam("instance") String instanceName,
+                                        @BinderParam(BindToJsonPayload.class)
+                                        Instance.NetworkInterface.AccessConfig accessConfig,
+                                        @QueryParam("network_interface") String networkInterfaceName);
+  
    /**
     * Deletes an access config from an instance's network interface.
     *
+    * @param zone zone instance is in
     * @param instanceName         the instance name.
     * @param accessConfigName     the name of the access config to delete
     * @param networkInterfaceName network interface name.
@@ -222,22 +237,146 @@ public interface InstanceApi {
    @Named("Instances:deleteAccessConfig")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances/{instance}/deleteAccessConfig")
+   @Path("/zones/{zone}/instances/{instance}/deleteAccessConfig")
    @OAuthScopes(COMPUTE_SCOPE)
-   Operation deleteAccessConfigFromNic(@PathParam("instance") String instanceName,
-                                       @QueryParam("access_config") String accessConfigName,
-                                       @QueryParam("network_interface") String networkInterfaceName);
+   Operation deleteAccessConfigFromNicInZone(@PathParam("zone") String zone,
+                                             @PathParam("instance") String instanceName,
+                                             @QueryParam("access_config") String accessConfigName,
+                                             @QueryParam("network_interface") String networkInterfaceName);
 
    /**
     * Returns the specified instance's serial port output.
     *
+    * @param zone zone instance is in
     * @param instanceName the instance name.
     * @return if successful, this method returns a SerialPortOutput containing the instance's serial output.
     */
    @Named("Instances:serialPort")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/instances/{instance}/serialPort")
+   @Path("/zones/{zone}/instances/{instance}/serialPort")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   Instance.SerialPortOutput getSerialPortOutput(@PathParam("instance") String instanceName);
+   Instance.SerialPortOutput getSerialPortOutputInZone(@PathParam("zone") String zone,
+                                                       @PathParam("instance") String instanceName);
+
+   /**
+    * Hard-resets the instance.
+    *
+    * @param zone         the zone the instance is in
+    * @param instanceName the instance name
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.  If the instance did not exist the result is null.
+    */
+   @Named("Instances:reset")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/zones/{zone}/instances/{instance}/reset")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation resetInZone(@PathParam("zone") String zone,
+                         @PathParam("instance") String instanceName);
+
+   /**
+    * Attaches a disk to an instance
+    *
+    * @param zone The zone the instance is in.
+    * @param instanceName The instance name to attach to
+    * @param attachDiskOptions The options for attaching the disk.
+    *
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Instances:attachDisk")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/zones/{zone}/instances/{instance}/attachDisk")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation attachDiskInZone(@PathParam("zone") String zone,
+                              @PathParam("instance") String instanceName,
+                              @BinderParam(BindToJsonPayload.class) AttachDiskOptions attachDiskOptions);
+
+   /**
+    * Detaches an attached disk from an instance
+    *
+    * @param zone The zone the instance is in.
+    * @param instanceName The instance name to attach to
+    * @param deviceName The device name of the disk to detach.
+    *
+    * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+    *         you, and look for the status field.
+    */
+   @Named("Instances:detachDisk")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/zones/{zone}/instances/{instance}/detachDisk")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Operation detachDiskInZone(@PathParam("zone") String zone,
+                              @PathParam("instance") String instanceName,
+                              @QueryParam("deviceName") String deviceName);
+
+   /**
+    * Sets metadata for an instance using the data included in the request.
+    * <p/>
+    * NOTE: This *sets* metadata items on the project (vs *adding* items to metadata),
+    * if there are pre-existing metadata items that must be kept these must be fetched first and then re-set on the
+    * new Metadata, e.g.
+    * <pre><tt>
+    *    Metadata.Builder current = instanceApi.getInZone("us-central1-a", "myInstance").getMetadata().toBuilder();
+    *    current.addItem("newItem","newItemValue");
+    *    instanceApi.setMetadataInZone("us-central1-a", "myInstance", current.build());
+    * </tt></pre>
+    *
+    * @param zone The zone the instance is in
+    * @param instanceName The name of the instance
+    * @param metadata the metadata to set
+    * @param fingerprint The current fingerprint for the items
+    *
+    * @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
+    *         to you, and look for the status field.
+    */
+   @Named("Instances:setMetadata")
+   @POST
+   @Path("/zones/{zone}/instances/{instance}/setMetadata")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @MapBinder(MetadataBinder.class)
+   @Nullable
+   Operation setMetadataInZone(@PathParam("zone") String zone,
+                               @PathParam("instance") String instanceName,
+                               @PayloadParam("items") Map<String, String> metadata,
+                               @PayloadParam("fingerprint") String fingerprint);
+
+   /**
+    * Sets items for an instance
+    *
+    * @param zone The zone the instance is in
+    * @param instanceName the name of the instance
+    * @param items A set of items
+    * @param fingerprint The current fingerprint for the items
+    * @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
+    *         to you, and look for the status field.
+    */
+   @Named("Instances:setTags")
+   @POST
+   @Path("/zones/{zone}/instances/{instance}/setTags")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @MapBinder(BindToJsonPayload.class)
+   @Nullable
+   Operation setTagsInZone(@PathParam("zone") String zone,
+                           @PathParam("instance") String instanceName,
+                           @PayloadParam("items") Set<String> items,
+                           @PayloadParam("fingerprint") String fingerprint);
+
 }
+

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/KernelApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/KernelApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/KernelApi.java
index a707bb5..76acf9c 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/KernelApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/KernelApi.java
@@ -47,7 +47,7 @@ import org.jclouds.rest.annotations.Transform;
  * Provides access to Kernels via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/kernels"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/kernels"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -62,7 +62,7 @@ public interface KernelApi {
     */
    @Named("Kernels:get")
    @GET
-   @Path("/kernels/{kernel}")
+   @Path("/global/kernels/{kernel}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    Kernel get(@PathParam("kernel") String kernelName);
@@ -72,7 +72,7 @@ public interface KernelApi {
     */
    @Named("Kernels:list")
    @GET
-   @Path("/kernels")
+   @Path("/global/kernels")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseKernels.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -83,7 +83,7 @@ public interface KernelApi {
     */
    @Named("Kernels:list")
    @GET
-   @Path("/kernels")
+   @Path("/global/kernels")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseKernels.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -102,19 +102,19 @@ public interface KernelApi {
     */
    @Named("Kernels:list")
    @GET
-   @Path("/kernels")
+   @Path("/global/kernels")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseKernels.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
    ListPage<Kernel> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
-                                                   ListOptions listOptions);
+                                 ListOptions listOptions);
 
    /**
     * @see KernelApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("Kernels:list")
    @GET
-   @Path("/kernels")
+   @Path("/global/kernels")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseKernels.class)
    @Transform(ParseKernels.ToPagedIterable.class)
@@ -130,7 +130,7 @@ public interface KernelApi {
     */
    @Named("Kernels:list")
    @GET
-   @Path("/kernels")
+   @Path("/global/kernels")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseKernels.class)
    @Transform(ParseKernels.ToPagedIterable.class)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/MachineTypeApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/MachineTypeApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/MachineTypeApi.java
index a27e2e4..acdd24f 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/MachineTypeApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/MachineTypeApi.java
@@ -47,7 +47,7 @@ import org.jclouds.rest.annotations.Transform;
  * Provides access to MachineTypes via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/machineTypes"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/machineTypes"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -57,44 +57,45 @@ public interface MachineTypeApi {
    /**
     * Returns the specified machine type resource
     *
+    * @param zone            the name of the zone the machine type is in
     * @param machineTypeName name of the machine type resource to return.
     * @return If successful, this method returns a MachineType resource
     */
    @Named("MachineTypes:get")
    @GET
-   @Path("/machineTypes/{machineType}")
+   @Path("/zones/{zone}/machineTypes/{machineType}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
-   MachineType get(@PathParam("machineType") String machineTypeName);
+   MachineType getInZone(@PathParam("zone") String zone, @PathParam("machineType") String machineTypeName);
 
    /**
-    * @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see MachineTypeApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("MachineTypes:list")
    @GET
-   @Path("/machineTypes")
+   @Path("/zones/{zone}/machineTypes")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseMachineTypes.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<MachineType> listFirstPage();
+   ListPage<MachineType> listFirstPageInZone(@PathParam("zone") String zone);
 
    /**
-    * @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see MachineTypeApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("MachineTypes:list")
    @GET
-   @Path("/machineTypes")
+   @Path("/zones/{zone}/machineTypes")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseMachineTypes.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<MachineType> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
+   ListPage<MachineType> listAtMarkerInZone(@PathParam("zone") String zone, @QueryParam("pageToken") @Nullable String marker);
 
    /**
     * Retrieves the list of machine type resources available to the specified project.
     * By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
     * been set.
     *
-    *
+    * @param zone        The name of 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
@@ -103,39 +104,41 @@ public interface MachineTypeApi {
     */
    @Named("MachineTypes:list")
    @GET
-   @Path("/machineTypes")
+   @Path("/zones/{zone}/machineTypes")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseMachineTypes.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<MachineType> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
-                                                        ListOptions listOptions);
+   ListPage<MachineType> listAtMarkerInZone(@PathParam("zone") String zone,
+                                            @QueryParam("pageToken") @Nullable String marker,
+                                            ListOptions listOptions);
 
    /**
-    * @see MachineTypeApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see MachineTypeApi#listInZone(String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("MachineTypes:list")
    @GET
-   @Path("/machineTypes")
+   @Path("/zones/{zone}/machineTypes")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseMachineTypes.class)
    @Transform(ParseMachineTypes.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<MachineType> list();
+   PagedIterable<MachineType> listInZone(@PathParam("zone") String zone);
 
    /**
-    * A paged version of MachineTypeApi#list()
+    * A paged version of MachineTypeApi#listInZone(String)
     *
+    * @param zone the zone to list in
     * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
     * @see PagedIterable
-    * @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see MachineTypeApi#listAtMarkerInZone(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
     */
    @Named("MachineTypes:list")
    @GET
-   @Path("/machineTypes")
+   @Path("/zones/{zone}/machineTypes")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseMachineTypes.class)
    @Transform(ParseMachineTypes.ToPagedIterable.class)
    @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<MachineType> list(ListOptions listOptions);
+   PagedIterable<MachineType> listInZone(@PathParam("zone") String zone, ListOptions listOptions);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/NetworkApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/NetworkApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/NetworkApi.java
index ca15787..5a04ccd 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/NetworkApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/NetworkApi.java
@@ -55,7 +55,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
  * Provides access to Networks via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/networks"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/networks"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -70,7 +70,7 @@ public interface NetworkApi {
    @Named("Networks:get")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks/{network}")
+   @Path("/global/networks/{network}")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    Network get(@PathParam("network") String networkName);
@@ -87,11 +87,11 @@ public interface NetworkApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes({COMPUTE_SCOPE})
    @MapBinder(BindToJsonPayload.class)
    Operation createInIPv4Range(@PayloadParam("name") String networkName,
-                                                 @PayloadParam("IPv4Range") String IPv4Range);
+                               @PayloadParam("IPv4Range") String IPv4Range);
 
    /**
     * Creates a persistent network resource in the specified project with the specified range and specified gateway.
@@ -106,12 +106,12 @@ public interface NetworkApi {
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes({COMPUTE_SCOPE})
    @MapBinder(BindToJsonPayload.class)
    Operation createInIPv4RangeWithGateway(@PayloadParam("name") String networkName,
-                                                            @PayloadParam("IPv4Range") String IPv4Range,
-                                                            @PayloadParam("gatewayIPv4") String gatewayIPv4);
+                                          @PayloadParam("IPv4Range") String IPv4Range,
+                                          @PayloadParam("gatewayIPv4") String gatewayIPv4);
 
    /**
     * Deletes the specified persistent network resource.
@@ -123,7 +123,7 @@ public interface NetworkApi {
    @Named("Networks:delete")
    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks/{network}")
+   @Path("/global/networks/{network}")
    @OAuthScopes(COMPUTE_SCOPE)
    @Fallback(NullOnNotFoundOr404.class)
    Operation delete(@PathParam("network") String networkName);
@@ -134,7 +134,7 @@ public interface NetworkApi {
    @Named("Networks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseNetworks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -146,7 +146,7 @@ public interface NetworkApi {
    @Named("Networks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseNetworks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
@@ -157,7 +157,6 @@ public interface NetworkApi {
     * By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
     * been set.
     *
-    *
     * @param marker      marks the beginning of the next list page
     * @param listOptions listing options
     * @return a page of the list
@@ -167,12 +166,12 @@ public interface NetworkApi {
    @Named("Networks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseNetworks.class)
    @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
    ListPage<Network> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
-                                                    ListOptions options);
+                                  ListOptions options);
 
    /**
     * @see NetworkApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
@@ -180,7 +179,7 @@ public interface NetworkApi {
    @Named("Networks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseNetworks.class)
    @Transform(ParseNetworks.ToPagedIterable.class)
@@ -197,7 +196,7 @@ public interface NetworkApi {
    @Named("Networks:list")
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/networks")
+   @Path("/global/networks")
    @OAuthScopes(COMPUTE_READONLY_SCOPE)
    @ResponseParser(ParseNetworks.class)
    @Transform(ParseNetworks.ToPagedIterable.class)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/OperationApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/OperationApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/OperationApi.java
deleted file mode 100644
index fc8da71..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/OperationApi.java
+++ /dev/null
@@ -1,159 +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.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.ParseOperations;
-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/v1beta13/operations"/>
- */
-@SkipEncoding({'/', '='})
-@RequestFilters(OAuthAuthenticator.class)
-public interface OperationApi {
-
-   /**
-    * Retrieves the specified operation resource.
-    *
-    * @param operationName name of the operation resource to return.
-    * @return If successful, this method returns an Operation resource
-    */
-   @Named("Operations:get")
-   @GET
-   @Path("/operations/{operation}")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   Operation get(@PathParam("operation") String operationName);
-
-   /**
-    * Deletes the specified operation resource.
-    *
-    * @param operationName name of the operation resource to delete.
-    */
-   @Named("Operations:delete")
-   @DELETE
-   @Path("/operations/{operation}")
-   @OAuthScopes(COMPUTE_SCOPE)
-   @Fallback(NullOnNotFoundOr404.class)
-   void delete(@PathParam("operation") String operationName);
-
-   /**
-    * @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
-    */
-   @Named("Operations:list")
-   @GET
-   @Path("/operations")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseOperations.class)
-   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Operation> listFirstPage();
-
-   /**
-    * @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
-    */
-   @Named("Operations:list")
-   @GET
-   @Path("/operations")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseOperations.class)
-   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Operation> listAtMarker(@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 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("Operations:list")
-   @GET
-   @Path("/operations")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseOperations.class)
-   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
-   ListPage<Operation> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
-                                                      ListOptions listOptions);
-
-   /**
-    * @see OperationApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
-    */
-   @Named("Operations:list")
-   @GET
-   @Path("/operations")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseOperations.class)
-   @Transform(ParseOperations.ToPagedIterable.class)
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Operation> list();
-
-   /**
-    * A paged version of OperationApi#listFirstPage()
-    *
-    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
-    * @see PagedIterable
-    * @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
-    */
-   @Named("Operations:list")
-   @GET
-   @Path("/operations")
-   @OAuthScopes(COMPUTE_READONLY_SCOPE)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseOperations.class)
-   @Transform(ParseOperations.ToPagedIterable.class)
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   PagedIterable<Operation> list(ListOptions listOptions);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
index d33d22d..acabab3 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/ProjectApi.java
@@ -36,8 +36,9 @@ import org.jclouds.googlecomputeengine.domain.Project;
 import org.jclouds.googlecomputeengine.handlers.MetadataBinder;
 import org.jclouds.oauth.v2.config.OAuthScopes;
 import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
-import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SkipEncoding;
 
@@ -45,7 +46,7 @@ import org.jclouds.rest.annotations.SkipEncoding;
  * Provides access to Projects via their REST API.
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/projects"/>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/projects"/>
  */
 @SkipEncoding({'/', '='})
 @RequestFilters(OAuthAuthenticator.class)
@@ -78,7 +79,8 @@ public interface ProjectApi {
     * </tt></pre>
     *
     * @param projectName            name of the project to return
-    * @param commonInstanceMetadata the metadata to set
+    * @param metadata the metadata to set
+    * @param fingerprint  The current fingerprint for the metadata
     * @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
     *         to you, and look for the status field.
     */
@@ -88,7 +90,8 @@ public interface ProjectApi {
    @OAuthScopes(COMPUTE_SCOPE)
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
+   @MapBinder(MetadataBinder.class)
    Operation setCommonInstanceMetadata(@PathParam("project") String projectName,
-                                                         @BinderParam(MetadataBinder.class)
-                                                         Map<String, String> commonInstanceMetadata);
+                                       @PayloadParam("items") Map<String, String> metadata,
+                                       @PayloadParam("fingerprint") String fingerprint);
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionApi.java
new file mode 100644
index 0000000..dcc81ad
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionApi.java
@@ -0,0 +1,136 @@
+/*
+ * 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 javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+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.Region;
+import org.jclouds.googlecomputeengine.functions.internal.ParseRegions;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+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 Regions via their REST API.
+ *
+ * @author David Alves
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15/regions"/>
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface RegionApi {
+
+   /**
+    * Returns the specified region resource
+    *
+    * @param regionName name of the region resource to return.
+    * @return If successful, this method returns a Region resource
+    */
+   @Named("Regions:get")
+   @GET
+   @Path("/regions/{region}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   Region get(@PathParam("region") String regionName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Regions:list")
+   @GET
+   @Path("/regions")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRegions.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Region> listFirstPage();
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Regions:list")
+   @GET
+   @Path("/regions")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRegions.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Region> listAtMarker(String marker);
+
+   /**
+    * Retrieves the listFirstPage of region resources available to 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 marker      marks the beginning of the next list page
+    * @param listOptions listing options
+    * @return a page of the listFirstPage
+    * @see org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("Regions:list")
+   @GET
+   @Path("/regions")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRegions.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Region> listAtMarker(String marker, ListOptions listOptions);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("Regions:list")
+   @GET
+   @Path("/regions")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRegions.class)
+   @Transform(ParseRegions.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Region> list();
+
+   /**
+    * A paged version of RegionApi#listFirstPage()
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.googlecomputeengine.features.RegionApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    * @see org.jclouds.collect.PagedIterable
+    */
+   @Named("Regions:list")
+   @GET
+   @Path("/regions")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @ResponseParser(ParseRegions.class)
+   @Transform(ParseRegions.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Region> list(ListOptions listOptions);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionOperationApi.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionOperationApi.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionOperationApi.java
new file mode 100644
index 0000000..0707f79
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/features/RegionOperationApi.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.ParseRegionOperations;
+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 RegionOperationApi {
+
+   /**
+    * Retrieves the specified operation resource.
+    *
+    * @param region        the region the operation is in
+    * @param operationName name of the operation resource to return.
+    * @return If successful, this method returns an Operation resource
+    */
+   @Named("RegionOperations:get")
+   @GET
+   @Path("/regions/{region}/operations/{operation}")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   Operation getInRegion(@PathParam("region") String region, @PathParam("operation") String operationName);
+
+   /**
+    * Deletes the specified operation resource.
+    *
+    * @param region        the region the operation is in
+    * @param operationName name of the operation resource to delete.
+    */
+   @Named("RegionOperations:delete")
+   @DELETE
+   @Path("/regions/{region}/operations/{operation}")
+   @OAuthScopes(COMPUTE_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   void deleteInRegion(@PathParam("region") String region, @PathParam("operation") String operationName);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionOperationApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("RegionOperations:list")
+   @GET
+   @Path("/regions/{region}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseRegionOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listFirstPageInRegion(@PathParam("region") String region);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionOperationApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("RegionOperations:list")
+   @GET
+   @Path("/regions/{region}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseRegionOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarkerInRegion(@PathParam("region") String region,
+                                            @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 region      the region 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 org.jclouds.googlecomputeengine.options.ListOptions
+    * @see org.jclouds.googlecomputeengine.domain.ListPage
+    */
+   @Named("RegionOperations:list")
+   @GET
+   @Path("/regions/{region}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseRegionOperations.class)
+   @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+   ListPage<Operation> listAtMarkerInRegion(@PathParam("region") String region,
+                                            @QueryParam("pageToken") @Nullable String marker,
+                                            ListOptions listOptions);
+
+   /**
+    * @see org.jclouds.googlecomputeengine.features.RegionOperationApi#listInRegion(String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("RegionOperations:list")
+   @GET
+   @Path("/regions/{region}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseRegionOperations.class)
+   @Transform(ParseRegionOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> listInRegion(@PathParam("region") String region);
+
+   /**
+    * A paged version of RegionOperationApi#listFirstPageInRegion(String)
+    *
+    * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+    * @see org.jclouds.collect.PagedIterable
+    * @see org.jclouds.googlecomputeengine.features.RegionOperationApi#listAtMarkerInRegion(String, String, org.jclouds.googlecomputeengine.options.ListOptions)
+    */
+   @Named("RegionOperations:list")
+   @GET
+   @Path("/regions/{region}/operations")
+   @OAuthScopes(COMPUTE_READONLY_SCOPE)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseRegionOperations.class)
+   @Transform(ParseRegionOperations.ToPagedIterable.class)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Operation> listInRegion(@PathParam("region") String region, ListOptions listOptions);
+
+}


[06/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/RouteBinder.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/RouteBinder.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/RouteBinder.java
new file mode 100644
index 0000000..e4a1232
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/handlers/RouteBinder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.handlers;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * @author Andrew Bayer
+ */
+public class RouteBinder implements MapBinder {
+
+   @Inject
+   private BindToJsonPayload jsonBinder;
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      RouteOptions options = (RouteOptions) checkNotNull(postParams.get("options"), "routeOptions");
+      String name = (String) checkNotNull(postParams.get("name"), "name");
+      URI network = (URI) checkNotNull(postParams.get("network"), "network");
+      options.name(name);
+      options.network(network);
+      return bindToRequest(request, options);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      return jsonBinder.bindToRequest(request, input);
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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..b1070d4
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/AttachDiskOptions.java
@@ -0,0 +1,129 @@
+/*
+ * 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;
+   private boolean boot;
+
+   /**
+    * 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;
+   }
+
+   /**
+    * Indicates that this is a boot disk. VM will use the first partition of the disk for its root filesystem.
+    *
+    * @return true if this is a boot disk, false otherwise
+    */
+   public boolean getBoot() {
+      return boot;
+   }
+
+   /**
+    * @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;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.options.AttachDiskOptions#getBoot()
+    */
+   public AttachDiskOptions boot(boolean boot) {
+      this.boot = boot;
+      return this;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/DeprecateOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/DeprecateOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/DeprecateOptions.java
new file mode 100644
index 0000000..aeaef6c
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/DeprecateOptions.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.options;
+
+import java.net.URI;
+import java.util.Date;
+
+/**
+ * Options to set the deprecation status of a resource. Currently only for images.
+ *
+ * @author Andrew Bayer
+ * @see <a href="https://developers.google.com/compute/docs/reference/latest/images/deprecate" />
+ */
+public class DeprecateOptions {
+
+   public enum State {
+      DEPRECATED,
+      OBSOLETE,
+      DELETED
+   }
+
+   private State state;
+   private URI replacement;
+   private Date deprecated;
+   private Date obsolete;
+   private Date deleted;
+
+   /**
+    * The new deprecation state.
+    *
+    * @return the new deprecation state.
+    */
+   public State getState() {
+      return state;
+   }
+
+   /**
+    * Optional URL for replacement of deprecated resource.
+    *
+    * @return the URL
+    */
+   public URI getReplacement() {
+      return replacement;
+   }
+
+   /**
+    * Optional RFC3339 timestamp for when the deprecation state was changed to DEPRECATED.
+    *
+    * @return the timestamp
+    */
+   public Date getDeprecated() {
+      return deprecated;
+   }
+
+   /**
+    * Optional RFC3339 timestamp for when the deprecation state was changed to OBSOLETE.
+    *
+    * @return the timestamp
+    */
+   public Date getObsolete() {
+      return obsolete;
+   }
+
+   /**
+    * Optional RFC3339 timestamp for when the deprecation state was changed to DELETED.
+    *
+    * @return the timestamp
+    */
+   public Date getDeleted() {
+      return deleted;
+   }
+
+   /**
+    * @see DeprecateOptions#getState()
+    */
+   public DeprecateOptions state(State state) {
+      this.state = state;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.options.DeprecateOptions#getReplacement()
+    */
+   public DeprecateOptions replacement(URI replacement) {
+      this.replacement = replacement;
+      return this;
+   }
+
+   /**
+    * @see DeprecateOptions#getDeprecated()
+    */
+   public DeprecateOptions deprecated(Date deprecated) {
+      this.deprecated = deprecated;
+      return this;
+   }
+
+   /**
+    * @see DeprecateOptions#getObsolete()
+    */
+   public DeprecateOptions obsolete(Date obsolete) {
+      this.obsolete = obsolete;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.options.DeprecateOptions#getDeleted()
+    */
+   public DeprecateOptions deleted(Date deleted) {
+      this.deleted = deleted;
+      return this;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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..5c3437c 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 {
 
@@ -135,6 +136,7 @@ public class FirewallOptions {
     */
    public FirewallOptions sourceTags(Set<String> sourceTags) {
       this.sourceTags = ImmutableSet.builder();
+      this.sourceTags.addAll(sourceTags);
       return this;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/RouteOptions.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/RouteOptions.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/RouteOptions.java
new file mode 100644
index 0000000..78dde4a
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/options/RouteOptions.java
@@ -0,0 +1,203 @@
+/*
+ * 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;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Options to create a route.
+ *
+ * @author Andrew Bayer
+ * @see org.jclouds.googlecomputeengine.domain.Route
+ */
+public class RouteOptions {
+
+   private String name;
+   private URI network;
+   private String destRange;
+   private URI nextHopInstance;
+   private String nextHopIp;
+   private URI nextHopNetwork;
+   private URI nextHopGateway;
+   private String description;
+   private Integer priority;
+
+   private ImmutableSet.Builder<String> tags = ImmutableSet.builder();
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getName()
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getName()
+    */
+   public RouteOptions name(String name) {
+      this.name = name;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getDescription()
+    */
+   public String getDescription() {
+      return description;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getDescription()
+    */
+   public RouteOptions description(String description) {
+      this.description = description;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getDestRange()
+    */
+   public String getDestRange() {
+      return destRange;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getDestRange()
+    */
+   public RouteOptions destRange(String destRange) {
+      this.destRange = destRange;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopIp()
+    */
+   public String getNextHopIp() {
+      return nextHopIp;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopIp()
+    */
+   public RouteOptions nextHopIp(String nextHopIp) {
+      this.nextHopIp = nextHopIp;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getPriority()
+    */
+   public Integer getPriority() {
+      return priority;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getPriority()
+    */
+   public RouteOptions priority(Integer priority) {
+      this.priority = priority;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNetwork()
+    */
+   public RouteOptions network(URI network) {
+      this.network = network;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNetwork()
+    */
+   public URI getNetwork() {
+      return network;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopInstance()
+    */
+   public RouteOptions nextHopInstance(URI nextHopInstance) {
+      this.nextHopInstance = nextHopInstance;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopInstance()
+    */
+   public URI getNextHopInstance() {
+      return nextHopInstance;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopNetwork()
+    */
+   public RouteOptions nextHopNetwork(URI nextHopNetwork) {
+      this.nextHopNetwork = nextHopNetwork;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopNetwork()
+    */
+   public URI getNextHopNetwork() {
+      return nextHopNetwork;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopGateway()
+    */
+   public RouteOptions nextHopGateway(URI nextHopGateway) {
+      this.nextHopGateway = nextHopGateway;
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getNextHopGateway()
+    */
+   public URI getNextHopGateway() {
+      return nextHopGateway;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getTags()
+    */
+   public Set<String> getTags() {
+      return tags.build();
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getTags()
+    */
+   public RouteOptions addTag(String tag) {
+      this.tags.add(tag);
+      return this;
+   }
+
+   /**
+    * @see org.jclouds.googlecomputeengine.domain.Route#getTags()
+    */
+   public RouteOptions tags(Set<String> tags) {
+      this.tags = ImmutableSet.builder();
+      this.tags.addAll(tags);
+      return this;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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-google/blob/53386380/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-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/RegionOperationDonePredicate.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/RegionOperationDonePredicate.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/RegionOperationDonePredicate.java
new file mode 100644
index 0000000..a4d1b9d
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/RegionOperationDonePredicate.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.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Region;
+
+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 RegionOperationDonePredicate implements Predicate<AtomicReference<Operation>> {
+
+   private final GoogleComputeEngineApi api;
+   private final Supplier<String> project;
+   private final Supplier<Map<URI, Region>> regions;
+
+   @Inject
+   RegionOperationDonePredicate(GoogleComputeEngineApi api, @UserProject Supplier<String> project,
+                                @Memoized Supplier<Map<URI, Region>> regions) {
+      this.api = api;
+      this.project = project;
+      this.regions = regions;
+   }
+
+   @Override
+   public boolean apply(AtomicReference<Operation> input) {
+      checkNotNull(input, "input");
+
+      Operation current = api.getRegionOperationApiForProject(project.get())
+              .getInRegion(regions.get().get(input.get().getRegion().get()).getName(),
+              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-google/blob/53386380/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..3cca34a
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/predicates/ZoneOperationDonePredicate.java
@@ -0,0 +1,70 @@
+/*
+ * 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-google/blob/53386380/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-google/blob/53386380/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();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceExpectTest.java
index 91e37ab..925ac6a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceExpectTest.java
@@ -16,47 +16,62 @@
  */
 package org.jclouds.googlecomputeengine.compute;
 
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.domain.Location;
-import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.features.InstanceApiExpectTest;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineServiceExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.util.Strings2;
-import org.testng.annotations.Test;
-
-import javax.ws.rs.core.MediaType;
-import java.io.IOException;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
 import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
 import static org.jclouds.googlecomputeengine.features.FirewallApiExpectTest.GET_FIREWALL_REQUEST;
+import static org.jclouds.googlecomputeengine.features.GlobalOperationApiExpectTest.GET_GLOBAL_OPERATION_REQUEST;
+import static org.jclouds.googlecomputeengine.features.GlobalOperationApiExpectTest.GET_GLOBAL_OPERATION_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_GOOGLE_IMAGES_REQUEST;
+import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_GOOGLE_IMAGES_RESPONSE;
 import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_PROJECT_IMAGES_REQUEST;
 import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_PROJECT_IMAGES_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_CENTRAL1B_INSTANCES_REQUEST;
+import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_CENTRAL1B_INSTANCES_RESPONSE;
 import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_INSTANCES_REQUEST;
 import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_INSTANCES_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_CENTRAL1B_MACHINE_TYPES_REQUEST;
+import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_CENTRAL1B_MACHINE_TYPES_RESPONSE;
 import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_MACHINE_TYPES_REQUEST;
 import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_MACHINE_TYPES_RESPONSE;
 import static org.jclouds.googlecomputeengine.features.NetworkApiExpectTest.GET_NETWORK_REQUEST;
-import static org.jclouds.googlecomputeengine.features.OperationApiExpectTest.GET_OPERATION_REQUEST;
-import static org.jclouds.googlecomputeengine.features.OperationApiExpectTest.GET_OPERATION_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.ProjectApiExpectTest.GET_PROJECT_REQUEST;
+import static org.jclouds.googlecomputeengine.features.ProjectApiExpectTest.GET_PROJECT_RESPONSE;
 import static org.jclouds.googlecomputeengine.features.ZoneApiExpectTest.LIST_ZONES_REQ;
 import static org.jclouds.googlecomputeengine.features.ZoneApiExpectTest.LIST_ZONES_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.ZoneApiExpectTest.LIST_ZONES_SHORT_RESPONSE;
+import static org.jclouds.googlecomputeengine.features.ZoneOperationApiExpectTest.GET_ZONE_OPERATION_REQUEST;
+import static org.jclouds.googlecomputeengine.features.ZoneOperationApiExpectTest.GET_ZONE_OPERATION_RESPONSE;
 import static org.jclouds.util.Strings2.toStringAndClose;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.features.InstanceApiExpectTest;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineServiceExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.util.Strings2;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
 
 /**
  * @author David Alves
@@ -64,20 +79,11 @@ import static org.testng.Assert.assertNotNull;
 @Test(groups = "unit")
 public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngineServiceExpectTest {
 
-   public static final HttpRequest LIST_GOOGLE_IMAGES_REQUEST = HttpRequest
-           .builder()
-           .method("GET")
-           .endpoint("https://www.googleapis.com/compute/v1beta13/projects/google/images")
-           .addHeader("Accept", "application/json")
-           .addHeader("Authorization", "Bearer " + TOKEN).build();
-
-   public static final HttpResponse LIST_GOOGLE_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
-           .payload(staticPayloadFromResource("/image_list_single_page.json")).build();
 
    private HttpRequest INSERT_NETWORK_REQUEST = HttpRequest
            .builder()
            .method("POST")
-           .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN)
            .payload(payloadFromStringWithContentType("{\"name\":\"jclouds-test\",\"IPv4Range\":\"10.0.0.0/8\"}",
@@ -87,12 +93,12 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
    private HttpRequest INSERT_FIREWALL_REQUEST = HttpRequest
            .builder()
            .method("POST")
-           .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls")
            .addHeader("Accept", "application/json")
            .addHeader("Authorization", "Bearer " + TOKEN)
            .payload(payloadFromStringWithContentType("{\"name\":\"jclouds-test\",\"network\":\"https://www.googleapis" +
-                   ".com/compute/v1beta13/projects/myproject/networks/jclouds-test\"," +
-                   "\"sourceRanges\":[\"10.0.0.0/8\",\"0.0.0.0/0\"],\"allowed\":[{\"IPProtocol\":\"tcp\"," +
+                   ".com/compute/v1beta15/projects/myproject/global/networks/jclouds-test\"," +
+                   "\"sourceRanges\":[\"10.0.0.0/8\",\"0.0.0.0/0\"],\"sourceTags\":[\"aTag\"],\"allowed\":[{\"IPProtocol\":\"tcp\"," +
                    "\"ports\":[\"22\"]}," +
                    "{\"IPProtocol\":\"udp\",\"ports\":[\"22\"]}]}",
                    MediaType.APPLICATION_JSON))
@@ -104,7 +110,7 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
                    " \"id\": \"13024414170909937976\",\n" +
                    " \"creationTimestamp\": \"2012-10-24T20:13:19.967\",\n" +
                    " \"selfLink\": \"https://www.googleapis" +
-                   ".com/compute/v1beta13/projects/myproject/networks/jclouds-test\",\n" +
+                   ".com/compute/v1beta15/projects/myproject/global/networks/jclouds-test\",\n" +
                    " \"name\": \"jclouds-test\",\n" +
                    " \"description\": \"test network\",\n" +
                    " \"IPv4Range\": \"10.0.0.0/8\",\n" +
@@ -114,6 +120,17 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
    private HttpResponse SUCESSFULL_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
            .payload(payloadFromResource("/operation.json")).build();
 
+   private HttpRequest SET_TAGS_REQUEST = HttpRequest.builder()
+           .method("POST")
+           .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-1/setTags")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN)
+           .payload(payloadFromStringWithContentType("{\"items\":[\"aTag\"],\"fingerprint\":\"abcd\"}",
+                   MediaType.APPLICATION_JSON))
+           .build();
+
+   private HttpResponse SET_TAGS_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(payloadFromResource("/operation.json")).build();
 
    private HttpResponse getInstanceResponseForInstanceAndNetworkAndStatus(String instanceName, String networkName,
                                                                           String status) throws
@@ -149,19 +166,17 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
       return HttpRequest
               .builder()
               .method("POST")
-              .endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN)
               .payload(payloadFromStringWithContentType("{\"name\":\"" + instanceName + "\"," +
                       "\"machineType\":\"https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1\"," +
-                      "\"zone\":\"https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/zones/us-central1-a\"," +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1\"," +
                       "\"image\":\"https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106\"," +
-                      "\"tags\":[],\"serviceAccounts\":[]," +
+                      ".com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106\"," +
+                      "\"serviceAccounts\":[]," +
                       "\"networkInterfaces\":[{\"network\":\"https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/" + networkName + "\"," +
+                      ".com/compute/v1beta15/projects/myproject/global/networks/" + networkName + "\"," +
                       "\"accessConfigs\":[{\"type\":\"ONE_TO_ONE_NAT\"}]}]," +
                       "\"metadata\":{\"kind\":\"compute#metadata\",\"items\":[{\"key\":\"sshKeys\"," +
                       "\"value\":\"jclouds:" +
@@ -174,7 +189,7 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
               .builder()
               .method("GET")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/" + instanceName)
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/" + instanceName)
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
    }
@@ -211,15 +226,29 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
       ImmutableMap<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.
               <HttpRequest, HttpResponse>builder()
               .put(requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE)
+              .put(GET_PROJECT_REQUEST, GET_PROJECT_RESPONSE)
               .put(LIST_ZONES_REQ, LIST_ZONES_RESPONSE)
               .put(LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE)
               .put(LIST_GOOGLE_IMAGES_REQUEST, LIST_GOOGLE_IMAGES_RESPONSE)
               .put(LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE)
+              .put(LIST_CENTRAL1B_MACHINE_TYPES_REQUEST, LIST_CENTRAL1B_MACHINE_TYPES_RESPONSE)
               .build();
 
       ComputeService client = requestsSendResponses(requestResponseMap);
       Template template = client.templateBuilder().build();
-      Template toMatch = client.templateBuilder().imageId(template.getImage().getId()).build();
+      Hardware defaultSize = client.templateBuilder().build().getHardware();
+
+      Hardware smallest = client.templateBuilder().smallest().build().getHardware();
+      assertEquals(defaultSize, smallest);
+
+      Hardware fastest = client.templateBuilder().fastest().build().getHardware();
+      assertNotNull(fastest);
+
+      assertEquals(client.listHardwareProfiles().size(), 5);
+
+      Template toMatch = client.templateBuilder()
+              .imageId(template.getImage().getId())
+              .build();
       assertEquals(toMatch.getImage(), template.getImage());
    }
 
@@ -229,26 +258,27 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
       HttpRequest deleteNodeRequest = HttpRequest.builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/test-delete-networks")
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-delete-networks")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
       HttpRequest deleteFirewallRequest = HttpRequest.builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test-delete")
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test-delete")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
       HttpRequest deleteNetworkReqquest = HttpRequest.builder()
               .method("DELETE")
               .endpoint("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/networks/jclouds-test-delete")
+                      ".com/compute/v1beta15/projects/myproject/global/networks/jclouds-test-delete")
               .addHeader("Accept", "application/json")
               .addHeader("Authorization", "Bearer " + TOKEN).build();
 
       List<HttpRequest> orderedRequests = ImmutableList.<HttpRequest>builder()
               .add(requestForScopes(COMPUTE_READONLY_SCOPE))
+              .add(GET_PROJECT_REQUEST)
               .add(getInstanceRequestForInstance("test-delete-networks"))
               .add(LIST_PROJECT_IMAGES_REQUEST)
               .add(LIST_GOOGLE_IMAGES_REQUEST)
@@ -256,56 +286,41 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
               .add(LIST_MACHINE_TYPES_REQUEST)
               .add(requestForScopes(COMPUTE_SCOPE))
               .add(deleteNodeRequest)
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_ZONE_OPERATION_REQUEST)
               .add(getInstanceRequestForInstance("test-delete-networks"))
-              .add(LIST_PROJECT_IMAGES_REQUEST)
-              .add(LIST_GOOGLE_IMAGES_REQUEST)
-              .add(LIST_ZONES_REQ)
-              .add(LIST_MACHINE_TYPES_REQUEST)
               .add(LIST_INSTANCES_REQUEST)
-              .add(LIST_PROJECT_IMAGES_REQUEST)
-              .add(LIST_GOOGLE_IMAGES_REQUEST)
-              .add(LIST_ZONES_REQ)
-              .add(LIST_MACHINE_TYPES_REQUEST)
               .add(deleteFirewallRequest)
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_GLOBAL_OPERATION_REQUEST)
               .add(deleteNetworkReqquest)
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_GLOBAL_OPERATION_REQUEST)
               .build();
 
 
       List<HttpResponse> orderedResponses = ImmutableList.<HttpResponse>builder()
               .add(TOKEN_RESPONSE)
+              .add(GET_PROJECT_RESPONSE)
               .add(getInstanceResponseForInstanceAndNetworkAndStatus("test-delete-networks", "test-network", Instance
                       .Status.RUNNING.name()))
               .add(LIST_PROJECT_IMAGES_RESPONSE)
               .add(LIST_GOOGLE_IMAGES_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
+              .add(LIST_ZONES_SHORT_RESPONSE)
               .add(LIST_MACHINE_TYPES_RESPONSE)
               .add(TOKEN_RESPONSE)
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_ZONE_OPERATION_RESPONSE)
               .add(getInstanceResponseForInstanceAndNetworkAndStatus("test-delete-networks", "test-network", Instance
                       .Status.TERMINATED.name()))
-              .add(LIST_PROJECT_IMAGES_RESPONSE)
-              .add(LIST_GOOGLE_IMAGES_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
-              .add(LIST_MACHINE_TYPES_RESPONSE)
               .add(getListInstancesResponseForSingleInstanceAndNetworkAndStatus("test-delete-networks",
                       "test-network", Instance
                       .Status.TERMINATED.name()))
-              .add(LIST_PROJECT_IMAGES_RESPONSE)
-              .add(LIST_GOOGLE_IMAGES_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
-              .add(LIST_MACHINE_TYPES_RESPONSE)
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_GLOBAL_OPERATION_RESPONSE)
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_GLOBAL_OPERATION_RESPONSE)
               .build();
 
       ComputeService client = orderedRequestsSendResponses(orderedRequests, orderedResponses);
-      client.destroyNode("test-delete-networks");
+      client.destroyNode("us-central1-a/test-delete-networks");
 
    }
 
@@ -314,11 +329,14 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
       ImmutableMap<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.
               <HttpRequest, HttpResponse>builder()
               .put(requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE)
+              .put(GET_PROJECT_REQUEST, GET_PROJECT_RESPONSE)
               .put(LIST_ZONES_REQ, LIST_ZONES_RESPONSE)
               .put(LIST_INSTANCES_REQUEST, LIST_INSTANCES_RESPONSE)
+              .put(LIST_CENTRAL1B_INSTANCES_REQUEST, LIST_CENTRAL1B_INSTANCES_RESPONSE)
               .put(LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE)
               .put(LIST_GOOGLE_IMAGES_REQUEST, LIST_GOOGLE_IMAGES_RESPONSE)
               .put(LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE)
+              .put(LIST_CENTRAL1B_MACHINE_TYPES_REQUEST, LIST_CENTRAL1B_MACHINE_TYPES_RESPONSE)
               .build();
 
       ComputeService apiWhenServersExist = requestsSendResponses(requestResponseMap);
@@ -331,7 +349,7 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
 
       assertNotNull(apiWhenServersExist.listNodes());
       assertEquals(apiWhenServersExist.listNodes().size(), 1);
-      assertEquals(apiWhenServersExist.listNodes().iterator().next().getId(), "test-0");
+      assertEquals(apiWhenServersExist.listNodes().iterator().next().getId(), "us-central1-a/test-0");
       assertEquals(apiWhenServersExist.listNodes().iterator().next().getName(), "test-0");
    }
 
@@ -347,65 +365,65 @@ public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngin
 
       List<HttpRequest> orderedRequests = ImmutableList.<HttpRequest>builder()
               .add(requestForScopes(COMPUTE_READONLY_SCOPE))
+              .add(GET_PROJECT_REQUEST)
               .add(LIST_ZONES_REQ)
               .add(LIST_PROJECT_IMAGES_REQUEST)
               .add(LIST_GOOGLE_IMAGES_REQUEST)
+              .add(LIST_ZONES_REQ)
               .add(LIST_MACHINE_TYPES_REQUEST)
               .add(GET_NETWORK_REQUEST)
               .add(requestForScopes(COMPUTE_SCOPE))
               .add(INSERT_NETWORK_REQUEST)
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_GLOBAL_OPERATION_REQUEST)
               .add(GET_NETWORK_REQUEST)
               .add(GET_FIREWALL_REQUEST)
               .add(INSERT_FIREWALL_REQUEST)
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_GLOBAL_OPERATION_REQUEST)
               .add(LIST_INSTANCES_REQUEST)
               .add(LIST_PROJECT_IMAGES_REQUEST)
               .add(LIST_GOOGLE_IMAGES_REQUEST)
-              .add(LIST_ZONES_REQ)
               .add(LIST_MACHINE_TYPES_REQUEST)
               .add(createInstanceRequestForInstance("test-1", "jclouds-test", openSshKey))
-              .add(GET_OPERATION_REQUEST)
+              .add(GET_ZONE_OPERATION_REQUEST)
+              .add(getInstanceRequestForInstance("test-1"))
+              .add(SET_TAGS_REQUEST)
+              .add(GET_ZONE_OPERATION_REQUEST)
               .add(getInstanceRequestForInstance("test-1"))
-              .add(LIST_PROJECT_IMAGES_REQUEST)
-              .add(LIST_GOOGLE_IMAGES_REQUEST)
-              .add(LIST_ZONES_REQ)
-              .add(LIST_MACHINE_TYPES_REQUEST)
               .build();
 
       List<HttpResponse> orderedResponses = ImmutableList.<HttpResponse>builder()
               .add(TOKEN_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
+              .add(GET_PROJECT_RESPONSE)
+              .add(LIST_ZONES_SHORT_RESPONSE)
               .add(LIST_PROJECT_IMAGES_RESPONSE)
               .add(LIST_GOOGLE_IMAGES_RESPONSE)
+              .add(LIST_ZONES_SHORT_RESPONSE)
               .add(LIST_MACHINE_TYPES_RESPONSE)
               .add(HttpResponse.builder().statusCode(404).build())
               .add(TOKEN_RESPONSE)
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_GLOBAL_OPERATION_RESPONSE)
               .add(GET_NETWORK_RESPONSE)
               .add(HttpResponse.builder().statusCode(404).build())
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_GLOBAL_OPERATION_RESPONSE)
               .add(LIST_INSTANCES_RESPONSE)
               .add(LIST_PROJECT_IMAGES_RESPONSE)
               .add(LIST_GOOGLE_IMAGES_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
               .add(LIST_MACHINE_TYPES_RESPONSE)
               .add(SUCESSFULL_OPERATION_RESPONSE)
-              .add(GET_OPERATION_RESPONSE)
+              .add(GET_ZONE_OPERATION_RESPONSE)
+              .add(getInstanceResponse)
+              .add(SET_TAGS_RESPONSE)
+              .add(GET_ZONE_OPERATION_RESPONSE)
               .add(getInstanceResponse)
-              .add(LIST_PROJECT_IMAGES_RESPONSE)
-              .add(LIST_GOOGLE_IMAGES_RESPONSE)
-              .add(LIST_ZONES_RESPONSE)
-              .add(LIST_MACHINE_TYPES_RESPONSE)
               .build();
 
 
       ComputeService computeService = orderedRequestsSendResponses(orderedRequests, orderedResponses);
 
       GoogleComputeEngineTemplateOptions options = computeService.templateOptions().as(GoogleComputeEngineTemplateOptions.class);
-
+      options.tags(ImmutableSet.of("aTag"));
       getOnlyElement(computeService.createNodesInGroup("test", 1, options));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java
index 2b76322..fbcd355 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceLiveTest.java
@@ -58,7 +58,7 @@ public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTe
    @Test(enabled = true, dependsOnMethods = "testReboot")
    public void testSuspendResume() throws Exception {
    }
-   
+
    @Test(enabled = true, dependsOnMethods = "testSuspendResume")
    public void testListNodesByIds() throws Exception {
       super.testGetNodesWithDetails();
@@ -76,7 +76,7 @@ public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTe
       super.testListNodes();
    }
 
-   @Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
+   @Test(enabled = true, dependsOnMethods = {"testListNodes", "testGetNodesWithDetails", "testListNodesByIds"})
    @Override
    public void testDestroyNodes() {
       super.testDestroyNodes();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImageTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImageTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImageTest.java
index f8301a2..1d1104f 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImageTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImageTest.java
@@ -16,14 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.googlecomputeengine.domain.Image;
-import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
 
 import java.net.URI;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertSame;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.googlecomputeengine.domain.Image;
+import org.testng.annotations.Test;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodesTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodesTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodesTest.java
index be998b6..40de63e 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodesTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodesTest.java
@@ -16,10 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
 import org.easymock.EasyMock;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.domain.ComputeMetadata;
@@ -28,13 +32,10 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
 import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
 import org.testng.annotations.Test;
 
-import java.util.Set;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiExpectTest.java
new file mode 100644
index 0000000..5ec5be9
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiExpectTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.parse.ParseAddressListTest;
+import org.jclouds.googlecomputeengine.parse.ParseAddressTest;
+import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class AddressApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   public void testGetAddressResponseIs2xx() throws Exception {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/address_get.json")).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getAddressApiForProject("myproject");
+
+      assertEquals(api.getInRegion("us-central1", "test-ip1"),
+              new ParseAddressTest().expected());
+   }
+
+   public void testGetAddressResponseIs4xx() throws Exception {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getAddressApiForProject("myproject");
+
+      assertNull(api.getInRegion("us-central1", "test-ip1"));
+   }
+
+   public void testInsertAddressResponseIs2xx() {
+      HttpRequest insert = HttpRequest
+              .builder()
+              .method("POST")
+              .endpoint("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN)
+              .payload(payloadFromResourceWithContentType("/address_insert.json", MediaType.APPLICATION_JSON))
+              .build();
+
+      HttpResponse insertAddressResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/region_operation.json")).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, insert,
+              insertAddressResponse).getAddressApiForProject("myproject");
+
+      assertEquals(api.createInRegion("us-central1", "test-ip1"), new ParseOperationTest().expected());
+   }
+
+   public void testDeleteAddressResponseIs2xx() {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/region_operation.json")).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, deleteResponse).getAddressApiForProject("myproject");
+
+      assertEquals(api.deleteInRegion("us-central1", "test-ip1"),
+              new ParseOperationTest().expected());
+   }
+
+   public void testDeleteAddressResponseIs4xx() {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, deleteResponse).getAddressApiForProject("myproject");
+
+      assertNull(api.deleteInRegion("us-central1", "test-ip1"));
+   }
+
+   public void testListAddresssResponseIs2xx() {
+      HttpRequest list = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/addresses")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/address_list.json")).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, list, operationResponse).getAddressApiForProject("myproject");
+
+      assertEquals(api.listFirstPageInRegion("us-central1").toString(),
+              new ParseAddressListTest().expected().toString());
+   }
+
+   public void testListAddresssResponseIs4xx() {
+      HttpRequest list = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/regions/us-central1/addresses")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      AddressApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, list, operationResponse).getAddressApiForProject("myproject");
+
+      assertTrue(api.listInRegion("us-central1").concat().isEmpty());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiLiveTest.java
new file mode 100644
index 0000000..356106f
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/AddressApiLiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Address;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author Andrew Bayer
+ */
+public class AddressApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String ADDRESS_NAME = "address-api-live-test-address";
+   private static final int TIME_WAIT = 30;
+
+   private AddressApi api() {
+      return api.getAddressApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testInsertAddress() {
+
+      assertRegionOperationDoneSucessfully(api().createInRegion(DEFAULT_REGION_NAME, ADDRESS_NAME), TIME_WAIT);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testInsertAddress")
+   public void testGetAddress() {
+      Address address = api().getInRegion(DEFAULT_REGION_NAME, ADDRESS_NAME);
+      assertNotNull(address);
+      assertEquals(address.getName(), ADDRESS_NAME);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testGetAddress")
+   public void testListAddress() {
+
+      PagedIterable<Address> addresss = api().listInRegion(DEFAULT_REGION_NAME, new ListOptions.Builder()
+              .filter("name eq " + ADDRESS_NAME));
+
+      List<Address> addresssAsList = Lists.newArrayList(addresss.concat());
+
+      assertEquals(addresssAsList.size(), 1);
+
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testListAddress")
+   public void testDeleteAddress() {
+
+      assertRegionOperationDoneSucessfully(api().deleteInRegion(DEFAULT_REGION_NAME, ADDRESS_NAME), TIME_WAIT);
+   }
+}


[11/11] git commit: JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Does not include aggregated list method calls, due to those calls not
working with service accounts.

Does not include image insert or deprecate due to the extremely
complex system for creating images in GCE, which makes writing tests
for that a pain. Will come in a later commit.


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

Branch: refs/heads/master
Commit: 53386380836e15ddb01e131b2ab9329e443d8b63
Parents: 2c45aca
Author: Andrew Bayer <an...@gmail.com>
Authored: Wed Jul 31 09:05:25 2013 -0700
Committer: Andrew Bayer <an...@gmail.com>
Committed: Wed Jul 31 09:05:25 2013 -0700

----------------------------------------------------------------------
 google-compute-engine/pom.xml                   | 220 +++++-----
 .../GoogleComputeEngineApi.java                 |  71 ++-
 .../GoogleComputeEngineApiMetadata.java         |  32 +-
 .../GoogleComputeEngineConstants.java           |   8 +-
 .../compute/GoogleComputeEngineService.java     |  44 +-
 .../GoogleComputeEngineServiceAdapter.java      | 168 +++++--
 ...GoogleComputeEngineServiceContextModule.java | 179 +++++---
 .../functions/BuildInstanceMetadata.java        |  11 +-
 .../GoogleComputeEngineImageToImage.java        |  25 +-
 .../functions/InstanceInZoneToNodeMetadata.java | 117 +++++
 .../functions/InstanceToNodeMetadata.java       | 111 -----
 .../functions/MachineTypeInZoneToHardware.java  | 102 +++++
 .../functions/MachineTypeToHardware.java        |  57 ---
 .../functions/OrphanedGroupsFromDeadNodes.java  |  12 +-
 .../compute/functions/RegionToLocation.java     |  47 ++
 .../compute/functions/ZoneToLocation.java       |   9 +-
 .../GoogleComputeEngineTemplateOptions.java     |  17 +-
 .../predicates/AllNodesInGroupTerminated.java   |  13 +-
 ...desWithGroupEncodedIntoNameThenAddToSet.java |  48 +-
 ...DefaultLoginCredentialsForImageStrategy.java |  18 +-
 ...eNodeCredentialsButOverrideFromTemplate.java |   9 +-
 .../GoogleComputeEngineHttpApiModule.java       |  78 +++-
 .../config/GoogleComputeEngineParserModule.java | 130 ++++--
 .../config/OAuthModuleWithoutTypeAdapters.java  |  19 +-
 .../googlecomputeengine/config/UserProject.java |   3 +-
 .../domain/AbstractDisk.java                    | 122 ++++++
 .../googlecomputeengine/domain/Address.java     | 178 ++++++++
 .../googlecomputeengine/domain/Deprecated.java  | 197 +++++++++
 .../googlecomputeengine/domain/Disk.java        |  71 +--
 .../googlecomputeengine/domain/Firewall.java    |  30 +-
 .../googlecomputeengine/domain/Image.java       |  50 ++-
 .../googlecomputeengine/domain/Instance.java    | 218 +++++++---
 .../domain/InstanceInZone.java                  |  55 +++
 .../domain/InstanceTemplate.java                |  80 +---
 .../googlecomputeengine/domain/Kernel.java      |  37 +-
 .../googlecomputeengine/domain/ListPage.java    |  17 +-
 .../googlecomputeengine/domain/MachineType.java | 119 ++---
 .../domain/MachineTypeInZone.java               |  55 +++
 .../googlecomputeengine/domain/Metadata.java    | 140 ++++++
 .../googlecomputeengine/domain/Network.java     |  12 +-
 .../googlecomputeengine/domain/Operation.java   |  77 +++-
 .../googlecomputeengine/domain/Project.java     |  44 +-
 .../googlecomputeengine/domain/Region.java      | 147 +++++++
 .../googlecomputeengine/domain/Resource.java    |  31 +-
 .../googlecomputeengine/domain/Route.java       | 434 +++++++++++++++++++
 .../domain/SlashEncodedIds.java                 |  86 ++++
 .../googlecomputeengine/domain/Snapshot.java    | 136 ++++++
 .../googlecomputeengine/domain/Zone.java        |  23 +-
 .../features/AddressApi.java                    | 188 ++++++++
 .../googlecomputeengine/features/DiskApi.java   |  78 ++--
 .../features/FirewallApi.java                   |  36 +-
 .../features/GlobalOperationApi.java            | 159 +++++++
 .../googlecomputeengine/features/ImageApi.java  |  20 +-
 .../features/InstanceApi.java                   | 213 +++++++--
 .../googlecomputeengine/features/KernelApi.java |  16 +-
 .../features/MachineTypeApi.java                |  43 +-
 .../features/NetworkApi.java                    |  29 +-
 .../features/OperationApi.java                  | 159 -------
 .../features/ProjectApi.java                    |  13 +-
 .../googlecomputeengine/features/RegionApi.java | 136 ++++++
 .../features/RegionOperationApi.java            | 164 +++++++
 .../googlecomputeengine/features/RouteApi.java  | 185 ++++++++
 .../features/SnapshotApi.java                   | 161 +++++++
 .../googlecomputeengine/features/ZoneApi.java   |   2 +-
 .../features/ZoneOperationApi.java              | 164 +++++++
 .../functions/internal/BaseToPagedIterable.java |  15 +-
 .../internal/BaseWithRegionToPagedIterable.java |  76 ++++
 .../internal/BaseWithZoneToPagedIterable.java   |  76 ++++
 .../functions/internal/PATCH.java               |   3 +-
 .../functions/internal/ParseAddresses.java      |  70 +++
 .../functions/internal/ParseDisks.java          |  22 +-
 .../functions/internal/ParseFirewalls.java      |  14 +-
 .../internal/ParseGlobalOperations.java         |  66 +++
 .../functions/internal/ParseImages.java         |  14 +-
 .../functions/internal/ParseInstances.java      |  22 +-
 .../functions/internal/ParseKernels.java        |  14 +-
 .../functions/internal/ParseMachineTypes.java   |  19 +-
 .../functions/internal/ParseNetworks.java       |  14 +-
 .../functions/internal/ParseOperations.java     |  64 ---
 .../internal/ParseRegionOperations.java         |  68 +++
 .../functions/internal/ParseRegions.java        |  66 +++
 .../functions/internal/ParseRoutes.java         |  66 +++
 .../functions/internal/ParseSnapshots.java      |  70 +++
 .../functions/internal/ParseZoneOperations.java |  68 +++
 .../functions/internal/ParseZones.java          |  14 +-
 .../handlers/FirewallBinder.java                |  13 +-
 .../GoogleComputeEngineErrorHandler.java        |   8 +-
 .../handlers/InstanceBinder.java                |  24 +-
 .../handlers/MetadataBinder.java                |  39 +-
 .../handlers/RouteBinder.java                   |  59 +++
 .../options/AttachDiskOptions.java              | 129 ++++++
 .../options/DeprecateOptions.java               | 127 ++++++
 .../options/FirewallOptions.java                |  10 +-
 .../options/ListOptions.java                    |   8 +-
 .../options/RouteOptions.java                   | 203 +++++++++
 .../GlobalOperationDonePredicate.java           |  61 +++
 .../predicates/OperationDonePredicate.java      |  60 ---
 .../RegionOperationDonePredicate.java           |  71 +++
 .../predicates/ZoneOperationDonePredicate.java  |  70 +++
 .../GoogleComputeEngineApiMetadataTest.java     |   5 +-
 .../PageSystemExpectTest.java                   |  14 +-
 .../GoogleComputeEngineServiceExpectTest.java   | 204 +++++----
 .../GoogleComputeEngineServiceLiveTest.java     |   4 +-
 .../GoogleComputeEngineImageToImageTest.java    |  10 +-
 .../OrphanedGroupsFromDeadNodesTest.java        |  23 +-
 .../features/AddressApiExpectTest.java          | 166 +++++++
 .../features/AddressApiLiveTest.java            |  74 ++++
 .../features/DiskApiExpectTest.java             |  92 ++--
 .../features/DiskApiLiveTest.java               |  20 +-
 .../features/FirewallApiExpectTest.java         |  62 +--
 .../features/FirewallApiLiveTest.java           |  33 +-
 .../features/GlobalOperationApiExpectTest.java  | 161 +++++++
 .../features/GlobalOperationApiLiveTest.java    |  94 ++++
 .../features/ImageApiExpectTest.java            |  33 +-
 .../features/ImageApiLiveTest.java              |  21 +-
 .../features/InstanceApiExpectTest.java         | 268 ++++++++++--
 .../features/InstanceApiLiveTest.java           | 138 +++++-
 .../features/KernelApiExpectTest.java           |  18 +-
 .../features/KernelApiLiveTest.java             |  19 +-
 .../features/MachineTypeApiExpectTest.java      |  36 +-
 .../features/MachineTypeApiLiveTest.java        |  23 +-
 .../features/NetworkApiExpectTest.java          |  30 +-
 .../features/NetworkApiLiveTest.java            |   4 +-
 .../features/OperationApiExpectTest.java        | 161 -------
 .../features/OperationApiLiveTest.java          |  93 ----
 .../features/ProjectApiExpectTest.java          |  41 +-
 .../features/ProjectApiLiveTest.java            |  43 +-
 .../features/RegionApiExpectTest.java           |  97 +++++
 .../features/RegionApiLiveTest.java             |  77 ++++
 .../features/RegionOperationApiExpectTest.java  | 198 +++++++++
 .../features/RegionOperationApiLiveTest.java    |  94 ++++
 .../features/RouteApiExpectTest.java            | 178 ++++++++
 .../features/RouteApiLiveTest.java              |  99 +++++
 .../features/SnapshotApiExpectTest.java         |  97 +++++
 .../features/SnapshotApiLiveTest.java           |  95 ++++
 .../features/ZoneApiExpectTest.java             |  16 +-
 .../features/ZoneApiLiveTest.java               |  19 +-
 .../features/ZoneOperationApiExpectTest.java    | 196 +++++++++
 .../features/ZoneOperationApiLiveTest.java      |  93 ++++
 .../GoogleComputeEngineErrorHandlerTest.java    |  18 +-
 .../BaseGoogleComputeEngineApiExpectTest.java   |   4 +-
 .../BaseGoogleComputeEngineApiLiveTest.java     |  71 ++-
 .../BaseGoogleComputeEngineExpectTest.java      |  73 ++--
 .../BaseGoogleComputeEngineParseTest.java       |   5 +-
 ...leComputeEngineServiceContextExpectTest.java |   7 +-
 .../parse/ParseAddressListTest.java             |  64 +++
 .../parse/ParseAddressTest.java                 |  54 +++
 .../parse/ParseDiskListTest.java                |  18 +-
 .../parse/ParseDiskTest.java                    |  13 +-
 .../parse/ParseFirewallListTest.java            |  16 +-
 .../parse/ParseFirewallTest.java                |  17 +-
 .../parse/ParseImageListTest.java               |  23 +-
 .../parse/ParseImageTest.java                   |  13 +-
 .../parse/ParseInstanceListTest.java            |  14 +-
 .../parse/ParseInstanceSerialOutputTest.java    |   6 +-
 .../parse/ParseInstanceTest.java                |  30 +-
 .../parse/ParseKernelListTest.java              |  29 +-
 .../parse/ParseKernelTest.java                  |  11 +-
 .../parse/ParseMachineTypeListTest.java         |  39 +-
 .../parse/ParseMachineTypeTest.java             |  16 +-
 .../parse/ParseMetadataTest.java                |  15 +-
 .../parse/ParseNetworkListTest.java             |  12 +-
 .../parse/ParseNetworkTest.java                 |  11 +-
 .../parse/ParseOperationListTest.java           |  15 +-
 .../parse/ParseOperationTest.java               |  16 +-
 .../parse/ParseProjectTest.java                 |  21 +-
 .../parse/ParseQuotaTest.java                   |   6 +-
 .../parse/ParseRegionListTest.java              |  66 +++
 .../parse/ParseRegionTest.java                  |  56 +++
 .../parse/ParseRouteListTest.java               |  65 +++
 .../parse/ParseRouteTest.java                   |  59 +++
 .../parse/ParseSnapshotListTest.java            |  67 +++
 .../parse/ParseSnapshotTest.java                |  55 +++
 .../parse/ParseZoneListTest.java                |  18 +-
 .../parse/ParseZoneTest.java                    |  11 +-
 .../src/test/resources/address_get.json         |  12 +
 .../src/test/resources/address_insert.json      |   1 +
 .../src/test/resources/address_list.json        |  31 ++
 .../test/resources/disk_create_snapshot.json    |   1 +
 .../src/test/resources/disk_get.json            |  16 +-
 .../src/test/resources/disk_insert.json         |   2 +-
 .../src/test/resources/disk_list.json           |  30 +-
 .../src/test/resources/firewall_get.json        |  52 +--
 .../src/test/resources/firewall_insert.json     |   2 +-
 .../src/test/resources/firewall_list.json       | 106 ++---
 .../src/test/resources/global_operation.json    |  15 +
 .../test/resources/global_operation_list.json   |  22 +
 .../src/test/resources/image_get.json           |  26 +-
 .../src/test/resources/image_insert.json        |   5 +-
 .../src/test/resources/image_list.json          |  44 +-
 .../resources/image_list_multiple_page_1.json   | 106 ++---
 .../resources/image_list_multiple_page_2.json   |  98 ++---
 .../test/resources/image_list_single_page.json  | 100 +++--
 .../resources/instance_add_access_config.json   |   8 +-
 .../test/resources/instance_attach_disk.json    |   6 +
 .../src/test/resources/instance_get.json        | 102 ++---
 .../src/test/resources/instance_insert.json     |   2 +-
 .../test/resources/instance_insert_simple.json  |   2 +-
 .../src/test/resources/instance_list.json       | 112 ++---
 .../instance_list_central1b_empty.json          |   6 +
 .../test/resources/instance_serial_port.json    |   4 +-
 .../test/resources/instance_set_metadata.json   |  10 +
 .../src/test/resources/kernel.json              |  12 +-
 .../src/test/resources/kernel_list.json         |  46 +-
 .../src/test/resources/logback.xml              |  41 +-
 .../src/test/resources/machinetype.json         |  39 +-
 .../src/test/resources/machinetype_list.json    |  94 ++--
 .../resources/machinetype_list_central1b.json   |  43 ++
 .../machinetype_list_central1b_empty.json       |   6 +
 .../src/test/resources/metadata.json            |   2 +-
 .../src/test/resources/network_get.json         |  16 +-
 .../src/test/resources/network_list.json        |  30 +-
 .../src/test/resources/operation.json           |  10 +-
 .../src/test/resources/operation_error.json     |  22 +-
 .../src/test/resources/operation_list.json      |  42 +-
 .../src/test/resources/project.json             | 131 +++---
 .../src/test/resources/region_get.json          |  13 +
 .../src/test/resources/region_list.json         |  32 ++
 .../src/test/resources/region_operation.json    |  16 +
 .../test/resources/region_operation_list.json   |  23 +
 .../src/test/resources/route_get.json           |  14 +
 .../src/test/resources/route_insert.json        |   1 +
 .../src/test/resources/route_list.json          |  34 ++
 .../src/test/resources/snapshot_get.json        |  13 +
 .../src/test/resources/snapshot_list.json       |  33 ++
 .../src/test/resources/tag_insert.json          |   1 +
 .../src/test/resources/zone_get.json            |  30 +-
 .../src/test/resources/zone_list.json           |  76 ++--
 .../src/test/resources/zone_list_short.json     |  24 +
 .../src/test/resources/zone_operation.json      |  16 +
 .../test/resources/zone_operation_error.json    |  25 ++
 .../src/test/resources/zone_operation_list.json |  23 +
 232 files changed, 10423 insertions(+), 2985 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/pom.xml
----------------------------------------------------------------------
diff --git a/google-compute-engine/pom.xml b/google-compute-engine/pom.xml
index 2461328..375192c 100644
--- a/google-compute-engine/pom.xml
+++ b/google-compute-engine/pom.xml
@@ -17,111 +17,123 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.apache.jclouds.labs</groupId>
-    <artifactId>jclouds-labs-google</artifactId>
-    <version>1.7.0-SNAPSHOT</version>
-  </parent>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.jclouds.labs</groupId>
+        <artifactId>jclouds-labs-google</artifactId>
+        <version>1.7.0-SNAPSHOT</version>
+    </parent>
 
-  <!-- TODO: when out of labs, switch to org.jclouds.provider -->
-  <groupId>org.apache.jclouds.labs</groupId>
-  <artifactId>google-compute-engine</artifactId>
-  <name>jclouds Google Compute Engine provider</name>
-  <description>jclouds components to access GoogleCompute</description>
+    <!-- TODO: when out of labs, switch to org.jclouds.provider -->
+    <groupId>org.apache.jclouds.labs</groupId>
+    <artifactId>google-compute-engine</artifactId>
+    <name>jclouds Google Compute Engine provider</name>
+    <description>jclouds components to access GoogleCompute</description>
 
-  <properties>
-    <test.google-compute-engine.identity>Email associated with the Google API client_id</test.google-compute-engine.identity>
-    <test.google-compute-engine.credential>Private key (PKCS12 file) associated with the Google API client_id</test.google-compute-engine.credential>
-    <test.google-compute-engine.api-version>v1beta13</test.google-compute-engine.api-version>
-    <test.google-compute-engine.build-version />
-  </properties>
+    <properties>
+        <test.google-compute-engine.identity>Email associated with the Google API client_id
+        </test.google-compute-engine.identity>
+        <test.google-compute-engine.credential>Private key (PKCS12 file) associated with the Google API client_id
+        </test.google-compute-engine.credential>
+        <test.google-compute-engine.api-version>v1beta15</test.google-compute-engine.api-version>
+        <test.google-compute-engine.build-version/>
+        <test.google-compute-engine.template>osFamily=GCEL,osVersionMatches=1[012].[01][04],locationId=us-central1-a,minRam=2048</test.google-compute-engine.template>
+    </properties>
 
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${jclouds.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.labs</groupId>
-      <artifactId>oauth</artifactId>
-      <version>${project.version}</version>
-      <type>jar</type>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.labs</groupId>
-      <artifactId>oauth</artifactId>
-      <version>${project.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-compute</artifactId>
-      <version>${jclouds.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-compute</artifactId>
-      <version>${jclouds.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds</groupId>
-      <artifactId>jclouds-core</artifactId>
-      <version>${jclouds.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-slf4j</artifactId>
-      <version>${jclouds.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.jclouds.driver</groupId>
-      <artifactId>jclouds-sshj</artifactId>
-      <version>${jclouds.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>ch.qos.logback</groupId>
-      <artifactId>logback-classic</artifactId>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <profiles>
-    <profile>
-      <id>live</id>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-surefire-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>integration</id>
-                <phase>integration-test</phase>
-                <goals>
-                  <goal>test</goal>
-                </goals>
-                <configuration>
-                  <systemPropertyVariables>
-                    <test.google-compute-engine.identity>${test.google-compute-engine.identity}</test.google-compute-engine.identity>
-                    <test.google-compute-engine.credential>${test.google-compute-engine.credential}</test.google-compute-engine.credential>
-                    <test.google-compute-engine.api-version>${test.google-compute-engine.api-version}</test.google-compute-engine.api-version>
-                    <test.google-compute-engine.build-version>${test.google-compute-engine.build-version}</test.google-compute-engine.build-version>
-                  </systemPropertyVariables>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.labs</groupId>
+            <artifactId>oauth</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.labs</groupId>
+            <artifactId>oauth</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-slf4j</artifactId>
+            <version>${jclouds.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-sshj</artifactId>
+            <version>${jclouds.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>live</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>integration</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <test.google-compute-engine.identity>${test.google-compute-engine.identity}
+                                        </test.google-compute-engine.identity>
+                                        <test.google-compute-engine.credential>
+                                            ${test.google-compute-engine.credential}
+                                        </test.google-compute-engine.credential>
+                                        <test.google-compute-engine.api-version>
+                                            ${test.google-compute-engine.api-version}
+                                        </test.google-compute-engine.api-version>
+                                        <test.google-compute-engine.build-version>
+                                            ${test.google-compute-engine.build-version}
+                                        </test.google-compute-engine.build-version>
+                                        <test.google-compute-engine.template>${test.google-compute-engine.template}</test.google-compute-engine.template>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/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 2567f0b..1f49bcc 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
@@ -21,16 +21,22 @@ import java.io.Closeable;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 
+import org.jclouds.googlecomputeengine.features.AddressApi;
 import org.jclouds.googlecomputeengine.features.DiskApi;
 import org.jclouds.googlecomputeengine.features.FirewallApi;
+import org.jclouds.googlecomputeengine.features.GlobalOperationApi;
 import org.jclouds.googlecomputeengine.features.ImageApi;
 import org.jclouds.googlecomputeengine.features.InstanceApi;
 import org.jclouds.googlecomputeengine.features.KernelApi;
 import org.jclouds.googlecomputeengine.features.MachineTypeApi;
 import org.jclouds.googlecomputeengine.features.NetworkApi;
-import org.jclouds.googlecomputeengine.features.OperationApi;
 import org.jclouds.googlecomputeengine.features.ProjectApi;
+import org.jclouds.googlecomputeengine.features.RegionApi;
+import org.jclouds.googlecomputeengine.features.RegionOperationApi;
+import org.jclouds.googlecomputeengine.features.RouteApi;
+import org.jclouds.googlecomputeengine.features.SnapshotApi;
 import org.jclouds.googlecomputeengine.features.ZoneApi;
+import org.jclouds.googlecomputeengine.features.ZoneOperationApi;
 import org.jclouds.rest.annotations.Delegate;
 
 import com.google.common.annotations.Beta;
@@ -41,12 +47,21 @@ import com.google.common.annotations.Beta;
  * <p/>
  *
  * @author David Alves
- * @see <a href="https://developers.google.com/compute/docs/reference/v1beta13">api doc</a>
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1beta15">api doc</a>
  */
 @Beta
 public interface GoogleComputeEngineApi extends Closeable {
 
    /**
+    * Provides access to Address features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   AddressApi getAddressApiForProject(@PathParam("project") String projectName);
+
+   /**
     * Provides access to Disk features
     *
     * @param projectName the name of the project
@@ -65,6 +80,15 @@ public interface GoogleComputeEngineApi extends Closeable {
    FirewallApi getFirewallApiForProject(@PathParam("project") String projectName);
 
    /**
+    * Provides access to Global Operation features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   GlobalOperationApi getGlobalOperationApiForProject(@PathParam("project") String projectName);
+
+   /**
     * Provides access to Image features
     *
     * @param projectName the name of the project
@@ -110,19 +134,46 @@ public interface GoogleComputeEngineApi extends Closeable {
    NetworkApi getNetworkApiForProject(@PathParam("project") String projectName);
 
    /**
-    * Provides access to Operation features
+    * Provides access to Project features
+    */
+   @Delegate
+   ProjectApi getProjectApi();
+
+   /**
+    * Provides access to Region features
     *
     * @param projectName the name of the project
     */
    @Delegate
    @Path("/projects/{project}")
-   OperationApi getOperationApiForProject(@PathParam("project") String projectName);
+   RegionApi getRegionApiForProject(@PathParam("project") String projectName);
 
    /**
-    * Provides access to Project features
+    * Provides access to Region Operation features
+    *
+    * @param projectName the name of the project
     */
    @Delegate
-   ProjectApi getProjectApi();
+   @Path("/projects/{project}")
+   RegionOperationApi getRegionOperationApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Route features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   RouteApi getRouteApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Snapshot features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   SnapshotApi getSnapshotApiForProject(@PathParam("project") String projectName);
 
    /**
     * Provides access to Zone features
@@ -133,5 +184,13 @@ public interface GoogleComputeEngineApi extends Closeable {
    @Path("/projects/{project}")
    ZoneApi getZoneApiForProject(@PathParam("project") String projectName);
 
+   /**
+    * Provides access to Zone Operation features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   ZoneOperationApi getZoneOperationApiForProject(@PathParam("project") String projectName);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
index c7e1f2a..0333f6c 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
@@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
 /**
- * Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
+ * Implementation of {@link ApiMetadata} for GoogleCompute v1beta15 API
  *
  * @author David Alves
  */
@@ -77,21 +77,21 @@ public class GoogleComputeEngineApiMetadata extends BaseHttpApiMetadata<GoogleCo
 
       protected Builder() {
          id(GCE_PROVIDER_NAME)
-        .name("Google Compute Engine Api")
-        .identityName("Email associated with the Google API client_id")
-        .credentialName("Private key literal associated with the Google API client_id")
-        .documentation(URI.create("https://developers.google.com/compute/docs"))
-        .version("v1beta13")
-        .defaultEndpoint("https://www.googleapis.com/compute/v1beta13")
-        .defaultProperties(GoogleComputeEngineApiMetadata.defaultProperties())
-        .view(typeToken(ComputeServiceContext.class))
-        .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
-                .add(GoogleComputeEngineHttpApiModule.class)
-                .add(GoogleComputeEngineParserModule.class)
-                .add(OAuthAuthenticationModule.class)
-                .add(OAuthModuleWithoutTypeAdapters.class)
-                .add(GoogleComputeEngineServiceContextModule.class)
-                .build());
+                 .name("Google Compute Engine Api")
+                 .identityName("Email associated with the Google API client_id")
+                 .credentialName("Private key literal associated with the Google API client_id")
+                 .documentation(URI.create("https://developers.google.com/compute/docs"))
+                 .version("v1beta15")
+                 .defaultEndpoint("https://www.googleapis.com/compute/v1beta15")
+                 .defaultProperties(GoogleComputeEngineApiMetadata.defaultProperties())
+                 .view(typeToken(ComputeServiceContext.class))
+                 .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                         .add(GoogleComputeEngineHttpApiModule.class)
+                         .add(GoogleComputeEngineParserModule.class)
+                         .add(OAuthAuthenticationModule.class)
+                         .add(OAuthModuleWithoutTypeAdapters.class)
+                         .add(GoogleComputeEngineServiceContextModule.class)
+                         .build());
       }
 
       @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
index dd83ce0..1334a32 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
@@ -16,11 +16,12 @@
  */
 package org.jclouds.googlecomputeengine;
 
-import com.google.common.annotations.Beta;
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 
+import com.google.common.annotations.Beta;
+
 /**
  * @author David Alves
  */
@@ -37,6 +38,11 @@ public interface GoogleComputeEngineConstants {
 
    public static final String COMPUTE_READONLY_SCOPE = "https://www.googleapis.com/auth/compute.readonly";
 
+   public static final String STORAGE_READONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.read_only";
+
+   public static final String STORAGE_WRITEONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.write_only";
+
+
    /**
     * The total time, in msecs, to wait for an operation to complete.
     */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
index e7b9e1c..4abcfc4 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
@@ -16,11 +16,23 @@
  */
 package org.jclouds.googlecomputeengine.compute;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+
 import org.jclouds.Constants;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.ComputeServiceContext;
@@ -54,21 +66,11 @@ import org.jclouds.googlecomputeengine.domain.Operation;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.scriptbuilder.functions.InitAdminAccess;
 
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Provider;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
-import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
-import static org.jclouds.util.Predicates2.retry;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
  * @author David Alves
@@ -117,7 +119,7 @@ public class GoogleComputeEngineService extends BaseComputeService {
                                         GroupNamingConvention.Factory namingConvention,
                                         GoogleComputeEngineApi api,
                                         @UserProject Supplier<String> project,
-                                        Predicate<AtomicReference<Operation>> operationDonePredicate,
+                                        @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate,
                                         @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
                                         @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
index aaa6271..b949f13 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
@@ -16,53 +16,62 @@
  */
 package org.jclouds.googlecomputeengine.compute;
 
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.UncheckedTimeoutException;
-import com.google.inject.Inject;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROJECT;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+
+import org.jclouds.collect.Memoized;
 import org.jclouds.compute.ComputeServiceAdapter;
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.options.TemplateOptions;
 import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
 import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
 import org.jclouds.googlecomputeengine.config.UserProject;
 import org.jclouds.googlecomputeengine.domain.Image;
 import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.InstanceInZone;
 import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
 import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.domain.MachineTypeInZone;
 import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
 import org.jclouds.googlecomputeengine.domain.Zone;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.logging.Logger;
 
-import javax.annotation.Resource;
-import javax.inject.Named;
-import java.net.URI;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.contains;
-import static com.google.common.collect.Iterables.filter;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROJECT;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
-import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
-import static org.jclouds.util.Predicates2.retry;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.google.inject.Inject;
 
 /**
  * @author David Alves
  */
-public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<Instance, MachineType, Image, Zone> {
+public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone> {
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@@ -70,6 +79,8 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
 
    private final GoogleComputeEngineApi api;
    private final Supplier<String> userProject;
+   private final Supplier<Map<URI, ? extends Location>> zones;
+   private final Supplier<Map<URI, ? extends Hardware>> hardwareMap;
    private final Function<TemplateOptions, ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions;
    private final Predicate<AtomicReference<Operation>> retryOperationDonePredicate;
    private final long operationCompleteCheckInterval;
@@ -80,9 +91,11 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
                                             @UserProject Supplier<String> userProject,
                                             Function<TemplateOptions,
                                                     ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions,
-                                            Predicate<AtomicReference<Operation>> operationDonePredicate,
+                                            @Named("zone") Predicate<AtomicReference<Operation>> operationDonePredicate,
                                             @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
-                                            @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
+                                            @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout,
+                                            @Memoized Supplier<Map<URI, ? extends Location>> zones,
+                                            @Memoized Supplier<Map<URI, ? extends Hardware>> hardwareMap) {
       this.api = checkNotNull(api, "google compute api");
       this.userProject = checkNotNull(userProject, "user project name");
       this.metatadaFromTemplateOptions = checkNotNull(metatadaFromTemplateOptions,
@@ -93,21 +106,24 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
               "operation completed check timeout");
       this.retryOperationDonePredicate = retry(operationDonePredicate, operationCompleteCheckTimeout,
               operationCompleteCheckInterval, TimeUnit.MILLISECONDS);
+      this.zones = checkNotNull(zones, "zones");
+      this.hardwareMap = checkNotNull(hardwareMap, "hardwareMap");
    }
 
    @Override
-   public NodeAndInitialCredentials<Instance> createNodeWithGroupEncodedIntoName(
-           final String group, final String name, Template template) {
+   public NodeAndInitialCredentials<InstanceInZone> createNodeWithGroupEncodedIntoName(
+           final String group, final String name, final Template template) {
 
       checkNotNull(template, "template");
 
       GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone();
       checkState(options.getNetwork().isPresent(), "network was not present in template options");
       Hardware hardware = checkNotNull(template.getHardware(), "hardware must be set");
-      URI machineType = checkNotNull(hardware.getUri(), "hardware uri must be set");
+
+      checkNotNull(hardware.getUri(), "hardware must have a URI");
 
       InstanceTemplate instanceTemplate = InstanceTemplate.builder()
-              .forMachineType(machineType);
+              .forMachineType(hardware.getUri());
 
       if (options.isEnableNat()) {
          instanceTemplate.addNetworkInterface(options.getNetwork().get(), Type.ONE_TO_ONE_NAT);
@@ -119,12 +135,11 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
 
       ImmutableMap.Builder<String, String> metadataBuilder = metatadaFromTemplateOptions.apply(options);
       instanceTemplate.metadata(metadataBuilder.build());
-      instanceTemplate.tags(options.getTags());
       instanceTemplate.serviceAccounts(options.getServiceAccounts());
       instanceTemplate.image(checkNotNull(template.getImage().getUri(), "image URI is null"));
 
       Operation operation = api.getInstanceApiForProject(userProject.get())
-              .createInZone(name, instanceTemplate, template.getLocation().getId());
+              .createInZone(name, template.getLocation().getId(), instanceTemplate);
 
       if (options.shouldBlockUntilRunning()) {
          waitOperationDone(operation);
@@ -136,18 +151,52 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
       retry(new Predicate<AtomicReference<Instance>>() {
          @Override
          public boolean apply(AtomicReference<Instance> input) {
-            input.set(api.getInstanceApiForProject(userProject.get()).get(name));
+            input.set(api.getInstanceApiForProject(userProject.get()).getInZone(template.getLocation().getId(),
+                    name));
             return input.get() != null;
          }
       }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance);
 
-      return new NodeAndInitialCredentials<Instance>(instance.get(), name, credentials);
+      if (options.getTags().size() > 0) {
+         Operation tagsOperation = api.getInstanceApiForProject(userProject.get()).setTagsInZone(template.getLocation().getId(),
+                 name, options.getTags(), instance.get().getTags().getFingerprint());
+
+         waitOperationDone(tagsOperation);
+
+         retry(new Predicate<AtomicReference<Instance>>() {
+            @Override
+            public boolean apply(AtomicReference<Instance> input) {
+               input.set(api.getInstanceApiForProject(userProject.get()).getInZone(template.getLocation().getId(),
+                       name));
+               return input.get() != null;
+            }
+         }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance);
+      }
+
+      InstanceInZone instanceInZone = new InstanceInZone(instance.get(), template.getLocation().getId());
+
+      return new NodeAndInitialCredentials<InstanceInZone>(instanceInZone, instanceInZone.slashEncode(), credentials);
    }
 
 
    @Override
-   public Iterable<MachineType> listHardwareProfiles() {
-      return api.getMachineTypeApiForProject(userProject.get()).list().concat();
+   public Iterable<MachineTypeInZone> listHardwareProfiles() {
+      ImmutableSet.Builder<MachineTypeInZone> builder = ImmutableSet.builder();
+
+      for (final Location zone : zones.get().values()) {
+         builder.addAll(api.getMachineTypeApiForProject(userProject.get())
+                 .listInZone(zone.getId())
+                 .concat()
+                 .transform(new Function<MachineType, MachineTypeInZone>() {
+
+                    @Override
+                    public MachineTypeInZone apply(MachineType arg0) {
+                       return new MachineTypeInZone(arg0, arg0.getZone());
+                    }
+                 }));
+      }
+
+      return builder.build();
    }
 
    @Override
@@ -170,34 +219,57 @@ public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<
    }
 
    @Override
-   public Instance getNode(String name) {
-      return api.getInstanceApiForProject(userProject.get()).get(name);
+   public InstanceInZone getNode(String name) {
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+
+      Instance instance= api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId());
+
+      return instance == null ?  null : new InstanceInZone(instance, slashEncodedIds.getFirstId());
    }
 
    @Override
-   public Iterable<Instance> listNodes() {
-      return api.getInstanceApiForProject(userProject.get()).list().concat();
+   public Iterable<InstanceInZone> listNodes() {
+      return FluentIterable.from(zones.get().values()).transformAndConcat(new Function<Location, ImmutableSet<InstanceInZone>>() {
+         @Override
+         public ImmutableSet<InstanceInZone> apply(final Location input) {
+            return api.getInstanceApiForProject(userProject.get()).listInZone(input.getId()).concat()
+                    .transform(new Function<Instance, InstanceInZone>() {
+
+                       @Override
+                       public InstanceInZone apply(Instance arg0) {
+                          return new InstanceInZone(arg0, input.getId());
+                       }
+                    }).toSet();
+         }
+      }).toSet();
    }
 
    @Override
-   public Iterable<Instance> listNodesByIds(final Iterable<String> ids) {
-      return filter(listNodes(), new Predicate<Instance>() {
+   public Iterable<InstanceInZone> listNodesByIds(final Iterable<String> ids) {
+      return filter(listNodes(), new Predicate<InstanceInZone>() {
 
          @Override
-         public boolean apply(Instance instance) {
-            return contains(ids, instance.getName());
+         public boolean apply(InstanceInZone instanceInZone) {
+            return contains(ids, instanceInZone.getInstance().getName());
          }
       });
    }
 
    @Override
    public void destroyNode(final String name) {
-      waitOperationDone(api.getInstanceApiForProject(userProject.get()).delete(name));
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+
+      waitOperationDone(api.getInstanceApiForProject(userProject.get()).deleteInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId()));
    }
 
    @Override
-   public void rebootNode(String name) {
-      throw new UnsupportedOperationException("reboot is not supported by GCE");
+   public void rebootNode(final String name) {
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+
+      waitOperationDone(api.getInstanceApiForProject(userProject.get()).resetInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId()));
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
index f3ecb6c..1e3580b 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
@@ -16,15 +16,19 @@
  */
 package org.jclouds.googlecomputeengine.compute.config;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Injector;
-import com.google.inject.Provides;
-import com.google.inject.TypeLiteral;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Maps.uniqueIndex;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceAdapter;
@@ -40,9 +44,10 @@ import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineService;
 import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineServiceAdapter;
 import org.jclouds.googlecomputeengine.compute.functions.BuildInstanceMetadata;
 import org.jclouds.googlecomputeengine.compute.functions.GoogleComputeEngineImageToImage;
-import org.jclouds.googlecomputeengine.compute.functions.InstanceToNodeMetadata;
-import org.jclouds.googlecomputeengine.compute.functions.MachineTypeToHardware;
+import org.jclouds.googlecomputeengine.compute.functions.InstanceInZoneToNodeMetadata;
+import org.jclouds.googlecomputeengine.compute.functions.MachineTypeInZoneToHardware;
 import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadNodes;
+import org.jclouds.googlecomputeengine.compute.functions.RegionToLocation;
 import org.jclouds.googlecomputeengine.compute.functions.ZoneToLocation;
 import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
 import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
@@ -52,22 +57,28 @@ import org.jclouds.googlecomputeengine.compute.strategy.UseNodeCredentialsButOve
 import org.jclouds.googlecomputeengine.config.UserProject;
 import org.jclouds.googlecomputeengine.domain.Image;
 import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.domain.InstanceInZone;
+import org.jclouds.googlecomputeengine.domain.MachineTypeInZone;
+import org.jclouds.googlecomputeengine.domain.Region;
 import org.jclouds.googlecomputeengine.domain.Zone;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
 
-import javax.inject.Singleton;
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Maps.uniqueIndex;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Injector;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author David Alves
  */
 public class GoogleComputeEngineServiceContextModule
-        extends ComputeServiceAdapterContextModule<Instance, MachineType, Image, Zone> {
+        extends ComputeServiceAdapterContextModule<InstanceInZone, MachineTypeInZone, Image, Zone> {
 
    @Override
    protected void configure() {
@@ -75,18 +86,22 @@ public class GoogleComputeEngineServiceContextModule
 
       bind(ComputeService.class).to(GoogleComputeEngineService.class);
 
-      bind(new TypeLiteral<ComputeServiceAdapter<Instance, MachineType, Image, Zone>>() {})
+      bind(new TypeLiteral<ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone>>() {})
               .to(GoogleComputeEngineServiceAdapter.class);
 
-      bind(new TypeLiteral<Function<Instance, NodeMetadata>>() {})
-              .to(InstanceToNodeMetadata.class);
+      bind(new TypeLiteral<Function<InstanceInZone, NodeMetadata>>() {})
+              .to(InstanceInZoneToNodeMetadata.class);
 
-      bind(new TypeLiteral<Function<MachineType, Hardware>>() {})
-              .to(MachineTypeToHardware.class);
+      bind(new TypeLiteral<Function<MachineTypeInZone, Hardware>>() {})
+              .to(MachineTypeInZoneToHardware.class);
 
       bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {})
               .to(GoogleComputeEngineImageToImage.class);
 
+      bind(new TypeLiteral<Function<Region, Location>>() {
+      })
+              .to(RegionToLocation.class);
+
       bind(new TypeLiteral<Function<Zone, Location>>() {})
               .to(ZoneToLocation.class);
 
@@ -108,7 +123,7 @@ public class GoogleComputeEngineServiceContextModule
 
       bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class);
 
-      install(new LocationsFromComputeServiceAdapterModule<Instance, MachineType, Image, Zone>() {});
+      install(new LocationsFromComputeServiceAdapterModule<InstanceInZone, MachineTypeInZone, Image, Zone>() {});
 
    }
 
@@ -116,56 +131,92 @@ public class GoogleComputeEngineServiceContextModule
    @Singleton
    @Memoized
    public Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>> provideImagesMap(
-           final Supplier<Set<? extends org.jclouds.compute.domain.Image>> images) {
-      return new Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>>() {
-         @Override
-         public Map<URI, ? extends org.jclouds.compute.domain.Image> get() {
-            return uniqueIndex(images.get(), new Function<org.jclouds.compute.domain.Image, URI>() {
-               @Override
-               public URI apply(org.jclouds.compute.domain.Image input) {
-                  return input.getUri();
-               }
-            });
-         }
-      };
+           AtomicReference<AuthorizationException> authException,
+           final Supplier<Set<? extends org.jclouds.compute.domain.Image>> images,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>>() {
+                 @Override
+                 public Map<URI, ? extends org.jclouds.compute.domain.Image> get() {
+                    return uniqueIndex(images.get(), new Function<org.jclouds.compute.domain.Image, URI>() {
+                       @Override
+                       public URI apply(org.jclouds.compute.domain.Image input) {
+                          return input.getUri();
+                       }
+                    });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
    }
 
    @Provides
    @Singleton
    @Memoized
    public Supplier<Map<URI, ? extends Hardware>> provideHardwaresMap(
-           final Supplier<Set<? extends Hardware>> hardwares) {
-      return new Supplier<Map<URI, ? extends Hardware>>() {
-         @Override
-         public Map<URI, ? extends Hardware> get() {
-            return uniqueIndex(hardwares.get(), new Function<Hardware, URI>() {
-               @Override
-               public URI apply(Hardware input) {
-                  return input.getUri();
-               }
-            });
-         }
-      };
+           AtomicReference<AuthorizationException> authException,
+           final Supplier<Set<? extends Hardware>> hardwares,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends Hardware>>() {
+                 @Override
+                 public Map<URI, ? extends Hardware> get() {
+                    return uniqueIndex(hardwares.get(), new Function<Hardware, URI>() {
+                       @Override
+                       public URI apply(Hardware input) {
+                          return input.getUri();
+                       }
+                    });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
    }
 
    @Provides
    @Singleton
    @Memoized
-   public Supplier<Map<URI, ? extends Location>> provideLocations(
+   public Supplier<Map<URI, ? extends Location>> provideZones(
+           AtomicReference<AuthorizationException> authException,
            final GoogleComputeEngineApi api, final Function<Zone, Location> zoneToLocation,
-           final @UserProject Supplier<String> userProject) {
-      return new Supplier<Map<URI, ? extends Location>>() {
-         @Override
-         public Map<URI, ? extends Location> get() {
-            return uniqueIndex(transform(api.getZoneApiForProject(userProject.get()).list().concat(), zoneToLocation),
-                    new Function<Location, URI>() {
-                       @Override
-                       public URI apply(Location input) {
-                          return (URI) input.getMetadata().get("selfLink");
-                       }
-                    });
-         }
-      };
+           final @UserProject Supplier<String> userProject,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends Location>>() {
+                 @Override
+                 public Map<URI, ? extends Location> get() {
+                    return uniqueIndex(transform(api.getZoneApiForProject(userProject.get()).list().concat(), zoneToLocation),
+                            new Function<Location, URI>() {
+                               @Override
+                               public URI apply(Location input) {
+                                  return (URI) input.getMetadata().get("selfLink");
+                               }
+                            });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<URI, Region>> provideRegions(
+           AtomicReference<AuthorizationException> authException,
+           final GoogleComputeEngineApi api,
+           final @UserProject Supplier<String> userProject,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, Region>>() {
+                 @Override
+                 public Map<URI, Region> get() {
+                    return uniqueIndex(api.getRegionApiForProject(userProject.get()).list().concat(),
+                            new Function<Region, URI>() {
+                               @Override
+                               public URI apply(Region input) {
+                                  return input.getSelfLink();
+                               }
+                            });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java
index 85837a7..27564e6 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java
@@ -16,14 +16,15 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import org.jclouds.compute.options.TemplateOptions;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
 
 import javax.inject.Singleton;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.String.format;
+import org.jclouds.compute.options.TemplateOptions;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * Prepares metadata from the provided TemplateOptions

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java
index ea5f893..f352879 100644
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java
@@ -16,21 +16,22 @@
  */
 package org.jclouds.googlecomputeengine.compute.functions;
 
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import org.jclouds.compute.domain.ImageBuilder;
-import org.jclouds.compute.domain.OperatingSystem;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.googlecomputeengine.domain.Image;
-
-import java.util.List;
-
 import static com.google.common.base.Joiner.on;
 import static com.google.common.collect.Iterables.getLast;
 import static com.google.common.collect.Iterables.limit;
 import static com.google.common.collect.Iterables.skip;
 import static org.jclouds.compute.domain.Image.Status;
-import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
+
+import java.util.List;
+
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.googlecomputeengine.domain.Image;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 
 /**
  * Transforms a google compute domain specific image to a generic Image object.
@@ -48,7 +49,6 @@ public class GoogleComputeEngineImageToImage implements Function<Image, org.jclo
               .providerId(image.getId())
               .description(image.getDescription().orNull())
               .status(Status.AVAILABLE)
-              .location(GOOGLE_PROVIDER_LOCATION)
               .uri(image.getSelfLink());
 
       List<String> splits = Lists.newArrayList(image.getName().split("-"));
@@ -65,6 +65,9 @@ public class GoogleComputeEngineImageToImage implements Function<Image, org.jclo
       String version = on(".").join(limit(skip(splits, 1), splits.size() - 2));
       osBuilder.version(version);
 
+      if (image.getDeprecated().isPresent()) {
+         builder.userMetadata(ImmutableMap.of("deprecatedState", image.getDeprecated().get().getState().orNull()));
+      }
       builder.version(getLast(splits));
       return builder.operatingSystem(osBuilder.build()).build();
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java
new file mode 100644
index 0000000..93ecaad
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.InstanceInZone;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Transforms a google compute domain Instance into a generic NodeMetatada object.
+ *
+ * @author David Alves
+ */
+public class InstanceInZoneToNodeMetadata implements Function<InstanceInZone, NodeMetadata> {
+
+   private final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus;
+   private final GroupNamingConvention nodeNamingConvention;
+   private final Supplier<Map<URI, ? extends Image>> images;
+   private final Supplier<Map<URI, ? extends Hardware>> hardwares;
+   private final Supplier<Map<URI, ? extends Location>> locations;
+
+   @Inject
+   public InstanceInZoneToNodeMetadata(Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus,
+                                 GroupNamingConvention.Factory namingConvention,
+                                 @Memoized Supplier<Map<URI, ? extends Image>> images,
+                                 @Memoized Supplier<Map<URI, ? extends Hardware>> hardwares,
+                                 @Memoized Supplier<Map<URI, ? extends Location>> locations) {
+      this.toPortableNodeStatus = toPortableNodeStatus;
+      this.nodeNamingConvention = namingConvention.createWithoutPrefix();
+      this.images = images;
+      this.hardwares = hardwares;
+      this.locations = locations;
+   }
+
+   @Override
+   public NodeMetadata apply(InstanceInZone instanceInZone) {
+      Instance input = instanceInZone.getInstance();
+      Map<URI, ? extends Image> imagesMap = images.get();
+      Image image = checkNotNull(imagesMap.get(checkNotNull(input.getImage(), "image")),
+              "no image for %s. images: %s", input.getImage(), imagesMap.values());
+
+      return new NodeMetadataBuilder()
+              .id(SlashEncodedIds.fromTwoIds(checkNotNull(locations.get().get(input.getZone()), "location for %s", input.getZone()).getId(),
+                      input.getName()).slashEncode())
+              .name(input.getName())
+              .providerId(input.getId())
+              .hostname(input.getName())
+              .imageId(image.getId())
+              .location(checkNotNull(locations.get().get(input.getZone()), "location for %s", input.getZone()))
+              .hardware(checkNotNull(hardwares.get().get(input.getMachineType()), "hardware type for %s",
+                      input.getMachineType().toString()))
+              .operatingSystem(image.getOperatingSystem())
+              .status(toPortableNodeStatus.get(input.getStatus()))
+              .tags(input.getTags().getItems())
+              .uri(input.getSelfLink())
+              .userMetadata(input.getMetadata().getItems())
+              .group(nodeNamingConvention.groupInUniqueNameOrNull(input.getName()))
+              .privateAddresses(collectPrivateAddresses(input))
+              .publicAddresses(collectPublicAddresses(input))
+              .build();
+   }
+
+   private Set<String> collectPrivateAddresses(Instance input) {
+      ImmutableSet.Builder<String> privateAddressesBuilder = ImmutableSet.builder();
+      for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
+         if (networkInterface.getNetworkIP().isPresent()) {
+            privateAddressesBuilder.add(networkInterface.getNetworkIP().get());
+         }
+      }
+      return privateAddressesBuilder.build();
+   }
+
+   private Set<String> collectPublicAddresses(Instance input) {
+      ImmutableSet.Builder<String> publicAddressesBuilder = ImmutableSet.builder();
+      for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
+         for (Instance.NetworkInterface.AccessConfig accessConfig : networkInterface.getAccessConfigs()) {
+            if (accessConfig.getNatIP().isPresent()) {
+               publicAddressesBuilder.add(accessConfig.getNatIP().get());
+            }
+         }
+      }
+      return publicAddressesBuilder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java
deleted file mode 100644
index 40be835..0000000
--- a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceToNodeMetadata.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.googlecomputeengine.compute.functions;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.collect.Memoized;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeMetadataBuilder;
-import org.jclouds.compute.functions.GroupNamingConvention;
-import org.jclouds.domain.Location;
-import org.jclouds.googlecomputeengine.domain.Instance;
-
-import javax.inject.Inject;
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Transforms a google compute domain Instance into a generic NodeMetatada object.
- *
- * @author David Alves
- */
-public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> {
-
-   private final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus;
-   private final GroupNamingConvention nodeNamingConvention;
-   private final Supplier<Map<URI, ? extends Image>> images;
-   private final Supplier<Map<URI, ? extends Hardware>> hardwares;
-   private final Supplier<Map<URI, ? extends Location>> locations;
-
-   @Inject
-   public InstanceToNodeMetadata(Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus,
-                                 GroupNamingConvention.Factory namingConvention,
-                                 @Memoized Supplier<Map<URI, ? extends Image>> images,
-                                 @Memoized Supplier<Map<URI, ? extends Hardware>> hardwares,
-                                 @Memoized Supplier<Map<URI, ? extends Location>> locations) {
-      this.toPortableNodeStatus = toPortableNodeStatus;
-      this.nodeNamingConvention = namingConvention.createWithoutPrefix();
-      this.images = images;
-      this.hardwares = hardwares;
-      this.locations = locations;
-   }
-
-   @Override
-   public NodeMetadata apply(Instance input) {
-      Map<URI, ? extends Image> imagesMap = images.get();
-      Image image = checkNotNull(imagesMap.get(checkNotNull(input.getImage(), "image")),
-              "no image for %s. images: %s", input.getImage(), imagesMap.values());
-
-      return new NodeMetadataBuilder()
-              .id(input.getName())
-              .name(input.getName())
-              .providerId(input.getId())
-              .hostname(input.getName())
-              .imageId(image.getId())
-              .location(checkNotNull(locations.get().get(input.getZone()), "location for %s", input.getZone()))
-              .hardware(checkNotNull(hardwares.get().get(input.getMachineType()), "hardware type for %s",
-                      input.getMachineType().toString()))
-              .operatingSystem(image.getOperatingSystem())
-              .status(toPortableNodeStatus.get(input.getStatus()))
-              .tags(input.getTags())
-              .uri(input.getSelfLink())
-              .userMetadata(input.getMetadata())
-              .group(nodeNamingConvention.groupInUniqueNameOrNull(input.getName()))
-              .privateAddresses(collectPrivateAddresses(input))
-              .publicAddresses(collectPublicAddresses(input))
-              .build();
-   }
-
-   private Set<String> collectPrivateAddresses(Instance input) {
-      ImmutableSet.Builder<String> privateAddressesBuilder = ImmutableSet.builder();
-      for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
-         if (networkInterface.getNetworkIP().isPresent()) {
-            privateAddressesBuilder.add(networkInterface.getNetworkIP().get());
-         }
-      }
-      return privateAddressesBuilder.build();
-   }
-
-   private Set<String> collectPublicAddresses(Instance input) {
-      ImmutableSet.Builder<String> publicAddressesBuilder = ImmutableSet.builder();
-      for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
-         for (Instance.NetworkInterface.AccessConfig accessConfig : networkInterface.getAccessConfigs()) {
-            if (accessConfig.getNatIP().isPresent()) {
-               publicAddressesBuilder.add(accessConfig.getNatIP().get());
-            }
-         }
-      }
-      return publicAddressesBuilder.build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java
new file mode 100644
index 0000000..9d94e32
--- /dev/null
+++ b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.getOnlyElement;
+
+import java.net.URI;
+import java.util.Map;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.domain.MachineTypeInZone;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+
+/**
+ * Transforms a google compute domain specific machine type to a generic Hardware object.
+ *
+ * @author David Alves
+ */
+public class MachineTypeInZoneToHardware implements Function<MachineTypeInZone, Hardware> {
+
+   private final Supplier<Map<URI, ? extends Location>> locations;
+
+   @Inject
+   public MachineTypeInZoneToHardware(@Memoized Supplier<Map<URI, ? extends Location>> locations) {
+      this.locations = locations;
+   }
+
+   @Override
+   public Hardware apply(final MachineTypeInZone input) {
+      Iterable<? extends Location> zonesForMachineType = filter(locations.get().values(), new Predicate<Location>() {
+         @Override
+         public boolean apply(Location l) {
+            return l.getId().equals(input.getMachineType().getZone());
+         }
+      });
+
+      Location location = checkNotNull(getOnlyElement(zonesForMachineType),
+              "location for %s",
+              input.getMachineType().getZone());
+
+      // TODO Figure out a robust way to deal with machineTypes with imageSizeGb==0 rather than just blocking them.
+      return new HardwareBuilder()
+              .id(SlashEncodedIds.fromTwoIds(input.getMachineType().getZone(), input.getMachineType().getName()).slashEncode())
+              .location(location)
+              .name(input.getMachineType().getName())
+              .hypervisor("kvm")
+              .processor(new Processor(input.getMachineType().getGuestCpus(), 1.0))
+              .providerId(input.getMachineType().getId())
+              .ram(input.getMachineType().getMemoryMb())
+              .uri(input.getMachineType().getSelfLink())
+              .userMetadata(ImmutableMap.of("imageSpaceGb", Integer.toString(input.getMachineType().getImageSpaceGb())))
+              .volumes(collectVolumes(input.getMachineType()))
+              .supportsImage(input.getMachineType().getImageSpaceGb() > 0
+                      ? Predicates.<Image>alwaysTrue()
+                      : Predicates.<Image>alwaysFalse())
+              .build();
+   }
+
+   private Iterable<Volume> collectVolumes(MachineType input) {
+      ImmutableSet.Builder<Volume> volumes = ImmutableSet.builder();
+      for (MachineType.ScratchDisk disk : input.getScratchDisks()) {
+         volumes.add(new VolumeBuilder()
+                 .type(Volume.Type.LOCAL)
+                 .size(new Integer(disk.getDiskGb()).floatValue())
+                 .bootDevice(true)
+                 .durable(false).build());
+      }
+      return volumes.build();
+   }
+}


[03/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiExpectTest.java
new file mode 100644
index 0000000..d5d5362
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiExpectTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Resource;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class ZoneOperationApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
+
+   private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
+           ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations";
+
+   public static final HttpRequest GET_ZONE_OPERATION_REQUEST = HttpRequest
+           .builder()
+           .method("GET")
+           .endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
+           .addHeader("Accept", "application/json")
+           .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   public static final HttpResponse GET_ZONE_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
+           .payload(staticPayloadFromResource("/zone_operation.json")).build();
+
+   private Operation expected() {
+      SimpleDateFormatDateService dateService = new SimpleDateFormatDateService();
+      return Operation.builder().id("13053095055850848306")
+              .selfLink(URI.create("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations/operation-1354084865060-4cf88735faeb8" +
+                      "-bbbb12cb"))
+              .name("operation-1354084865060-4cf88735faeb8-bbbb12cb")
+              .targetLink(URI.create("https://www.googleapis" +
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/instance-api-live-test-instance"))
+              .targetId("13053094017547040099")
+              .status(Operation.Status.DONE)
+              .user("user@developer.gserviceaccount.com")
+              .progress(100)
+              .insertTime(dateService.iso8601DateParse("2012-11-28T06:41:05.060"))
+              .startTime(dateService.iso8601DateParse("2012-11-28T06:41:05.142"))
+              .endTime(dateService.iso8601DateParse("2012-11-28T06:41:06.142"))
+              .operationType("insert")
+              .zone(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"))
+              .build();
+   }
+
+   private ListPage<Operation> expectedList() {
+      return ListPage.<Operation>builder()
+              .kind(Resource.Kind.OPERATION_LIST)
+              .id("projects/myproject/zones/us-central1-a/operations")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/operations"))
+              .addItem(expected())
+              .build();
+   }
+
+   public void testGetOperationResponseIs2xx() throws Exception {
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_ZONE_OPERATION_REQUEST, GET_ZONE_OPERATION_RESPONSE).getZoneOperationApiForProject("myproject");
+
+      assertEquals(zoneOperationApi.getInZone("us-central1-a", "operation-1354084865060-4cf88735faeb8-bbbb12cb"),
+              expected());
+   }
+
+   public void testGetOperationResponseIs4xx() throws Exception {
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, GET_ZONE_OPERATION_REQUEST, operationResponse).getZoneOperationApiForProject("myproject");
+
+      assertNull(zoneOperationApi.getInZone("us-central1-a", "operation-1354084865060-4cf88735faeb8-bbbb12cb"));
+   }
+
+   public void testDeleteOperationResponseIs2xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(204).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getZoneOperationApiForProject("myproject");
+
+      zoneOperationApi.deleteInZone("us-central1-a", "operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testDeleteOperationResponseIs4xx() throws Exception {
+      HttpRequest delete = HttpRequest
+              .builder()
+              .method("DELETE")
+              .endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
+              TOKEN_RESPONSE, delete, operationResponse).getZoneOperationApiForProject("myproject");
+
+      zoneOperationApi.deleteInZone("us-central1-a", "operation-1352178598164-4cdcc9d031510-4aa46279");
+   }
+
+   public void testListOperationWithNoOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation_list.json")).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getZoneOperationApiForProject("myproject");
+
+      assertEquals(zoneOperationApi.listFirstPageInZone("us-central1-a").toString(),
+              expectedList().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs2xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX +
+                      "?pageToken=CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcG" +
+                      "VyYXRpb24tMTM1MjI0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz&" +
+                      "filter=" +
+                      "status%20eq%20done&" +
+                      "maxResults=3")
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResource("/zone_operation_list.json")).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getZoneOperationApiForProject("myproject");
+
+      assertEquals(zoneOperationApi.listAtMarkerInZone("us-central1-a",
+              "CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcGVyYXRpb24tMTM1Mj" +
+                      "I0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz",
+              new ListOptions.Builder().filter("status eq done").maxResults(3)).toString(),
+              expectedList().toString());
+   }
+
+   public void testListOperationWithPaginationOptionsResponseIs4xx() {
+      HttpRequest get = HttpRequest
+              .builder()
+              .method("GET")
+              .endpoint(OPERATIONS_URL_PREFIX)
+              .addHeader("Accept", "application/json")
+              .addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
+
+      ZoneOperationApi zoneOperationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
+              TOKEN_RESPONSE, get, operationResponse).getZoneOperationApiForProject("myproject");
+
+      assertTrue(zoneOperationApi.listInZone("us-central1-a").concat().isEmpty());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiLiveTest.java
new file mode 100644
index 0000000..6ea4774
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/features/ZoneOperationApiLiveTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.features.DiskApiLiveTest.TIME_WAIT;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
+import org.jclouds.googlecomputeengine.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Andrew Bayer
+ */
+public class ZoneOperationApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
+
+   private static final String DISK_NAME = "zone-operations-api-live-test-disk";
+   private Operation addOperation;
+   private Operation deleteOperation;
+
+   private ZoneOperationApi api() {
+      return api.getZoneOperationApiForProject(userProject.get());
+   }
+
+   private DiskApi diskApi() {
+      return api.getDiskApiForProject(userProject.get());
+   }
+
+   @Test(groups = "live")
+   public void testCreateOperations() {
+      //create some operations by creating and deleting a disk
+      // this will make sure there is stuff to listFirstPage
+      addOperation = assertZoneOperationDoneSucessfully(diskApi().createInZone(DISK_NAME, 1, DEFAULT_ZONE_NAME), TIME_WAIT);
+      deleteOperation = assertZoneOperationDoneSucessfully(diskApi().deleteInZone(DEFAULT_ZONE_NAME, DISK_NAME), TIME_WAIT);
+
+      assertNotNull(addOperation);
+      assertNotNull(deleteOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testGetOperation() {
+      Operation operation = api().getInZone(DEFAULT_ZONE_NAME, addOperation.getName());
+      assertNotNull(operation);
+      assertOperationEquals(operation, this.addOperation);
+   }
+
+   @Test(groups = "live", dependsOnMethods = "testCreateOperations")
+   public void testListOperationsWithFiltersAndPagination() {
+      PagedIterable<Operation> operations = api().listInZone(DEFAULT_ZONE_NAME, new ListOptions.Builder()
+//              .filter("operationType eq insert")
+              .maxResults(1));
+
+      // make sure that in spite of having only one result per page we get at least two results
+      final AtomicInteger counter = new AtomicInteger();
+      operations.firstMatch(new Predicate<IterableWithMarker<Operation>>() {
+
+         @Override
+         public boolean apply(IterableWithMarker<Operation> input) {
+            counter.addAndGet(Iterables.size(input));
+            return counter.get() == 2;
+         }
+      });
+   }
+
+   private void assertOperationEquals(Operation result, Operation expected) {
+      assertEquals(result.getName(), expected.getName());
+   }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandlerTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandlerTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandlerTest.java
index e4f4cbb..ccad321 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandlerTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/handlers/GoogleComputeEngineErrorHandlerTest.java
@@ -16,20 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.handlers;
 
-import org.easymock.IArgumentMatcher;
-import org.jclouds.http.HttpCommand;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.Test;
-
-import java.net.URI;
-
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reportMatcher;
 import static org.easymock.EasyMock.verify;
 
+import java.net.URI;
+
+import org.easymock.IArgumentMatcher;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
 /**
  * @author Adrian Cole
  */
@@ -40,7 +40,7 @@ public class GoogleComputeEngineErrorHandlerTest {
    public void test409MakesIllegalStateException() {
       assertCodeMakes(
               "POST",
-              URI.create("https://www.googleapis.com/compute/v1beta13"),
+              URI.create("https://www.googleapis.com/compute/v1beta15"),
               409,
               "HTTP/1.1 409 Conflict",
               "\"{\"code\":\"InvalidState\",\"message\":\"An incompatible transition has already been queued for this" +

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiExpectTest.java
index f6760fb..ae7be6a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiExpectTest.java
@@ -16,10 +16,10 @@
  */
 package org.jclouds.googlecomputeengine.internal;
 
-import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
-
 import java.util.Properties;
 
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+
 /**
  * @author Adrian Cole
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiLiveTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiLiveTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiLiveTest.java
index 07a8fab..93567b8 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiLiveTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiLiveTest.java
@@ -36,6 +36,7 @@ import com.google.inject.Injector;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
 
 
 /**
@@ -43,20 +44,28 @@ import com.google.inject.TypeLiteral;
  */
 public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleComputeEngineApi> {
 
-   protected static final String API_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/";
+   protected static final String API_URL_PREFIX = "https://www.googleapis.com/compute/v1beta15/projects/";
    protected static final String ZONE_API_URL_SUFFIX = "/zones/";
    protected static final String DEFAULT_ZONE_NAME = "us-central1-a";
 
-   protected static final String NETWORK_API_URL_SUFFIX = "/networks/";
+   protected static final String REGION_API_URL_SUFFIX = "/region/";
+   protected static final String DEFAULT_REGION_NAME = "us-central1";
+
+   protected static final String NETWORK_API_URL_SUFFIX = "/global/networks/";
    protected static final String DEFAULT_NETWORK_NAME = "live-test-network";
 
    protected static final String MACHINE_TYPE_API_URL_SUFFIX = "/machineTypes/";
    protected static final String DEFAULT_MACHINE_TYPE_NAME = "n1-standard-1";
 
+   protected static final String GATEWAY_API_URL_SUFFIX = "/global/gateways/";
+   protected static final String DEFAULT_GATEWAY_NAME = "default-internet-gateway";
+
    protected static final String GOOGLE_PROJECT = "google";
 
    protected Supplier<String> userProject;
-   protected Predicate<AtomicReference<Operation>> operationDonePredicate;
+   protected Predicate<AtomicReference<Operation>> globalOperationDonePredicate;
+   protected Predicate<AtomicReference<Operation>> regionOperationDonePredicate;
+   protected Predicate<AtomicReference<Operation>> zoneOperationDonePredicate;
 
 
    public BaseGoogleComputeEngineApiLiveTest() {
@@ -67,20 +76,46 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
       Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
       userProject = injector.getInstance(Key.get(new TypeLiteral<Supplier<String>>() {
       }, UserProject.class));
-      operationDonePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
-      }));
+      globalOperationDonePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }, Names.named("global")));
+      regionOperationDonePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }, Names.named("region")));
+      zoneOperationDonePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+      }, Names.named("zone")));
       return injector.getInstance(GoogleComputeEngineApi.class);
    }
 
-   protected Operation assertOperationDoneSucessfully(Operation operation, long maxWaitSeconds) {
-      operation = waitOperationDone(operation, maxWaitSeconds);
+   protected Operation assertGlobalOperationDoneSucessfully(Operation operation, long maxWaitSeconds) {
+      operation = waitGlobalOperationDone(operation, maxWaitSeconds);
+      assertEquals(operation.getStatus(), Operation.Status.DONE);
+      assertTrue(operation.getErrors().isEmpty());
+      return operation;
+   }
+
+   protected Operation waitGlobalOperationDone(Operation operation, long maxWaitSeconds) {
+      return waitOperationDone(globalOperationDonePredicate, operation, maxWaitSeconds);
+   }
+
+   protected Operation assertRegionOperationDoneSucessfully(Operation operation, long maxWaitSeconds) {
+      operation = waitRegionOperationDone(operation, maxWaitSeconds);
       assertEquals(operation.getStatus(), Operation.Status.DONE);
       assertTrue(operation.getErrors().isEmpty());
       return operation;
    }
 
-   protected Operation waitOperationDone(Operation operation, long maxWaitSeconds) {
-      return waitOperationDone(operationDonePredicate, operation, maxWaitSeconds);
+   protected Operation waitRegionOperationDone(Operation operation, long maxWaitSeconds) {
+      return waitOperationDone(regionOperationDonePredicate, operation, maxWaitSeconds);
+   }
+
+   protected Operation assertZoneOperationDoneSucessfully(Operation operation, long maxWaitSeconds) {
+      operation = waitZoneOperationDone(operation, maxWaitSeconds);
+      assertEquals(operation.getStatus(), Operation.Status.DONE);
+      assertTrue(operation.getErrors().isEmpty());
+      return operation;
+   }
+
+   protected Operation waitZoneOperationDone(Operation operation, long maxWaitSeconds) {
+      return waitOperationDone(zoneOperationDonePredicate, operation, maxWaitSeconds);
    }
 
    protected URI getDefaultZoneUrl(String project) {
@@ -99,22 +134,28 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
       return URI.create(API_URL_PREFIX + project + NETWORK_API_URL_SUFFIX + network);
    }
 
-   protected URI getDefaultMachineTypekUrl(String project) {
-      return gettMachineTypeUrl(project, DEFAULT_MACHINE_TYPE_NAME);
+   protected URI getGatewayUrl(String project, String gateway) {
+      return URI.create(API_URL_PREFIX + project + GATEWAY_API_URL_SUFFIX + gateway);
+   }
+
+   protected URI getDefaultMachineTypeUrl(String project) {
+      return getMachineTypeUrl(project, DEFAULT_MACHINE_TYPE_NAME);
    }
 
-   protected URI gettMachineTypeUrl(String project, String machineType) {
-      return URI.create(API_URL_PREFIX + project + MACHINE_TYPE_API_URL_SUFFIX + machineType);
+   protected URI getMachineTypeUrl(String project, String machineType) {
+      return URI.create(API_URL_PREFIX + project + ZONE_API_URL_SUFFIX
+              + DEFAULT_ZONE_NAME + MACHINE_TYPE_API_URL_SUFFIX + machineType);
    }
 
    protected URI getDiskUrl(String project, String diskName) {
-      return URI.create(API_URL_PREFIX + project + "/disks/" + diskName);
+      return URI.create(API_URL_PREFIX + project + ZONE_API_URL_SUFFIX
+              + DEFAULT_ZONE_NAME + "/disks/" + diskName);
    }
 
    protected static Operation waitOperationDone(Predicate<AtomicReference<Operation>> operationDonePredicate,
                                                 Operation operation, long maxWaitSeconds) {
       AtomicReference<Operation> operationReference = new AtomicReference<Operation>(operation);
-      retry(operationDonePredicate,  maxWaitSeconds, 1, SECONDS).apply(operationReference);
+      retry(operationDonePredicate, maxWaitSeconds, 1, SECONDS).apply(operationReference);
       return operationReference.get();
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
index 7ca8ac1..bb2eec1 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
@@ -16,25 +16,19 @@
  */
 package org.jclouds.googlecomputeengine.internal;
 
-import com.google.common.base.Joiner;
-import com.google.common.base.Supplier;
-import com.google.common.base.Ticker;
-import com.google.inject.Binder;
-import com.google.inject.Module;
-import com.google.inject.TypeLiteral;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.collect.PagedIterables;
-import org.jclouds.crypto.Crypto;
-import org.jclouds.googlecomputeengine.domain.ListPage;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.io.Payload;
-import org.jclouds.oauth.v2.OAuthConstants;
-import org.jclouds.rest.internal.BaseRestApiExpectTest;
-import org.jclouds.ssh.SshKeys;
-import org.jclouds.util.Strings2;
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.io.BaseEncoding.base64Url;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.jclouds.crypto.Pems.privateKeySpec;
+import static org.jclouds.crypto.Pems.publicKeySpec;
+import static org.jclouds.crypto.PemsTest.PRIVATE_KEY;
+import static org.jclouds.crypto.PemsTest.PUBLIC_KEY;
+import static org.jclouds.io.Payloads.newStringPayload;
 
-import javax.ws.rs.core.MediaType;
 import java.io.IOException;
 import java.net.URI;
 import java.security.KeyFactory;
@@ -49,18 +43,26 @@ import java.security.spec.InvalidKeySpecException;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import static com.google.common.base.Charsets.UTF_8;
-import static com.google.common.base.Throwables.propagate;
-import static com.google.common.io.BaseEncoding.base64Url;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.jclouds.crypto.Pems.privateKeySpec;
-import static org.jclouds.crypto.Pems.publicKeySpec;
-import static org.jclouds.crypto.PemsTest.PRIVATE_KEY;
-import static org.jclouds.crypto.PemsTest.PUBLIC_KEY;
-import static org.jclouds.io.Payloads.newStringPayload;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.PagedIterables;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.io.Payload;
+import org.jclouds.oauth.v2.OAuthConstants;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+import org.jclouds.ssh.SshKeys;
+import org.jclouds.util.Strings2;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Supplier;
+import com.google.common.base.Ticker;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
 
 /**
  * @author Adrian Cole
@@ -151,6 +153,17 @@ public class BaseGoogleComputeEngineExpectTest<T> extends BaseRestApiExpectTest<
       return props;
    }
 
+   @Override
+   protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
+      HttpRequestComparisonType reqType = HttpRequestComparisonType.DEFAULT;
+      if (input.getPayload() != null) {
+         if (input.getPayload().getContentMetadata().getContentType().equals(MediaType.APPLICATION_JSON)) {
+            reqType = HttpRequestComparisonType.JSON;
+         }
+      }
+      return reqType;
+   }
+
    protected HttpRequest requestForScopes(String... scopes) {
       String claims = String.format(CLAIMS_TEMPLATE, Joiner.on(",").join(scopes));
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineParseTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineParseTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineParseTest.java
index e24e279..5dfa34c 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineParseTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineParseTest.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.internal;
 
-import com.google.inject.Guice;
-import com.google.inject.Injector;
 import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
 import org.jclouds.json.BaseItemParserTest;
 import org.jclouds.json.config.GsonModule;
 
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
 /**
  * @author David Alves
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineServiceContextExpectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineServiceContextExpectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineServiceContextExpectTest.java
index 12caaf6..21ddff3 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineServiceContextExpectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineServiceContextExpectTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.internal;
 
-import com.google.common.base.Function;
-import com.google.inject.Module;
+import java.util.Properties;
+
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.googlecomputeengine.GoogleComputeEngineApiMetadata;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 
-import java.util.Properties;
+import com.google.common.base.Function;
+import com.google.inject.Module;
 
 /**
  * @author David Alves

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressListTest.java
new file mode 100644
index 0000000..4043d23
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressListTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Address;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Resource.Kind;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class ParseAddressListTest extends BaseGoogleComputeEngineParseTest<ListPage<Address>> {
+
+   @Override
+   public String resource() {
+      return "/address_list.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public ListPage<Address> expected() {
+      return ListPage.<Address>builder()
+              .kind(Kind.ADDRESS_LIST)
+              .id("projects/myproject/regions/us-central1/addresses")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses"))
+              .items(ImmutableSet.of(new ParseAddressTest().expected(),
+                      Address.builder()
+                              .id("4881363978908129158")
+                              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-26T14:08:21.552-07:00"))
+                              .status("RESERVED")
+                              .region(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"))
+                              .name("test-ip2")
+                              .description("")
+                              .address("173.255.118.115")
+                              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip2"))
+                              .build())
+              ).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressTest.java
new file mode 100644
index 0000000..0441012
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseAddressTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Address;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class ParseAddressTest extends BaseGoogleComputeEngineParseTest<Address> {
+
+   @Override
+   public String resource() {
+      return "/address_get.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Address expected() {
+      return Address.builder()
+              .id("4439373783165447583")
+              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-26T13:57:20.204-07:00"))
+              .status("RESERVED")
+              .region(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"))
+              .name("test-ip1")
+              .description("")
+              .address("173.255.115.190")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1"))
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskListTest.java
index ebde5e4..7b83d8e 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskListTest.java
@@ -16,7 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Disk;
 import org.jclouds.googlecomputeengine.domain.ListPage;
@@ -24,9 +28,7 @@ import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -44,17 +46,17 @@ public class ParseDiskListTest extends BaseGoogleComputeEngineParseTest<ListPage
    public ListPage<Disk> expected() {
       return ListPage.<Disk>builder()
               .kind(Resource.Kind.DISK_LIST)
-              .id("projects/myproject/disks")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks"))
+              .id("projects/myproject/zones/us-central1-a/disks")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks"))
               .items(ImmutableSet.of(Disk.builder()
                       .id("13050421646334304115")
                       .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-11-25T01:38:48.306"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/disks/testimage1"))
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
                       .name("testimage1")
                       .sizeGb(1)
                       .zone(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-a"))
                       .status("READY")
                       .build())
               ).build();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskTest.java
index 31a9501..83cea8d 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseDiskTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Disk;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -42,10 +43,10 @@ public class ParseDiskTest extends BaseGoogleComputeEngineParseTest<Disk> {
       return Disk.builder()
               .id("13050421646334304115")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-11-25T01:38:48.306"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
               .name("testimage1")
               .sizeGb(1)
-              .zone(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
+              .zone(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"))
               .status("READY")
               .build();
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallListTest.java
index 1f0b39e..a90f17b 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallListTest.java
@@ -16,7 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Firewall;
 import org.jclouds.googlecomputeengine.domain.ListPage;
@@ -24,9 +28,7 @@ import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -45,18 +47,18 @@ public class ParseFirewallListTest extends BaseGoogleComputeEngineParseTest<List
       return ListPage.<Firewall>builder()
               .kind(Resource.Kind.FIREWALL_LIST)
               .id("projects/google/firewalls")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/firewalls"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/firewalls"))
               .items(ImmutableSet.of(
                       new ParseFirewallTest().expected()
                       , Firewall.builder()
                       .id("12862241067393040785")
                       .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-04-13T03:05:04.365"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/google/firewalls/default-ssh"))
+                              ".com/compute/v1beta15/projects/google/global/firewalls/default-ssh"))
                       .name("default-ssh")
                       .description("SSH allowed from anywhere")
                       .network(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/google/networks/default"))
+                              ".com/compute/v1beta15/projects/google/global/networks/default"))
                       .addSourceRange("0.0.0.0/0")
                       .addAllowed(Firewall.Rule.builder()
                               .IPProtocol(Firewall.Rule.IPProtocol.TCP)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallTest.java
index 1b9b8e2..187380f 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseFirewallTest.java
@@ -16,16 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.googlecomputeengine.domain.Firewall;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
-import org.testng.annotations.Test;
+import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
+
+import java.net.URI;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
-import java.net.URI;
 
-import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
 
 /**
  * @author David Alves
@@ -44,10 +45,10 @@ public class ParseFirewallTest extends BaseGoogleComputeEngineParseTest<Firewall
       return Firewall.builder()
               .id("12862241031274216284")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-04-13T03:05:02.855"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test"))
               .name("jclouds-test")
               .description("Internal traffic from default allowed")
-              .network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test"))
+              .network(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/jclouds-test"))
               .addSourceRange("10.0.0.0/8")
               .addAllowed(Firewall.Rule.builder()
                       .IPProtocol(IPProtocol.TCP)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageListTest.java
index 245f0d2..1f57299 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageListTest.java
@@ -16,17 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Deprecated;
 import org.jclouds.googlecomputeengine.domain.Image;
 import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -44,18 +47,22 @@ public class ParseImageListTest extends BaseGoogleComputeEngineParseTest<ListPag
    public ListPage<Image> expected() {
       return ListPage.<Image>builder()
               .kind(Resource.Kind.IMAGE_LIST)
-              .id("projects/google/images")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/images"))
+              .id("projects/google/global/images")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/images"))
               .items(ImmutableSet.of(Image.builder()
                       .id("12941197498378735318")
                       .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-07-16T22:16:13.468"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326"))
+                              ".com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326"))
                       .name("centos-6-2-v20120326")
                       .description("DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000")
                       .sourceType("RAW")
                       .preferredKernel(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/google/kernels/gce-20120326"))
+                              ".com/compute/v1beta15/projects/google/kernels/gce-20120326"))
+                      .deprecated(Deprecated.builder()
+                              .state("DEPRECATED")
+                              .replacement(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-v20130104"))
+                              .build())
                       .rawDisk(
                               Image.RawDisk.builder()
                                       .source("")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageTest.java
index 22c0016..a62e59a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseImageTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Image;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -42,13 +43,13 @@ public class ParseImageTest extends BaseGoogleComputeEngineParseTest<Image> {
       return Image.builder()
               .id("12941197498378735318")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-07-16T22:16:13.468"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2" +
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2" +
                       "-v20120326"))
               .name("centos-6-2-v20120326")
               .description("DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000")
               .sourceType("RAW")
               .preferredKernel(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/kernels/gce-20120326"))
+                      ".com/compute/v1beta15/projects/google/kernels/gce-20120326"))
               .rawDisk(
                       Image.RawDisk.builder()
                               .source("")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceListTest.java
index 9917914..3bd010d 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceListTest.java
@@ -16,15 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.domain.Instance;
 import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -41,8 +43,8 @@ public class ParseInstanceListTest extends BaseGoogleComputeEngineParseTest<List
    public ListPage<Instance> expected() {
       return ListPage.<Instance>builder()
               .kind(Resource.Kind.INSTANCE_LIST)
-              .id("projects/myproject/instances")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances"))
+              .id("projects/myproject/zones/us-central1-a/instances")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances"))
               .items(ImmutableSet.of(new ParseInstanceTest().expected()))
               .build();
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceSerialOutputTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceSerialOutputTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceSerialOutputTest.java
index f6091ba..c64fca3 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceSerialOutputTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceSerialOutputTest.java
@@ -16,12 +16,12 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import org.jclouds.googlecomputeengine.domain.Instance;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
-
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
 
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+
 /**
  * @author David Alves
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceTest.java
index 1940f86..26fa0ce 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseInstanceTest.java
@@ -16,14 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableMap;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.Metadata;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * @author David Alves
@@ -42,21 +45,21 @@ public class ParseInstanceTest extends BaseGoogleComputeEngineParseTest<Instance
               .id("13051190678907570425")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-11-25T23:48:20.758"))
               .selfLink(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/test-0"))
+                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-0"))
               .description("desc")
               .name("test-0")
               .image(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106"))
-              .machineType(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1" +
+                      ".com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106"))
+              .machineType(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1" +
                       "-standard-1"))
               .status(Instance.Status.RUNNING)
-              .zone(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
+              .zone(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"))
               .addNetworkInterface(
                       Instance.NetworkInterface.builder()
                               .name("nic0")
                               .networkIP("10.240.121.115")
                               .network(URI.create("https://www.googleapis" +
-                                      ".com/compute/v1beta13/projects/myproject/networks/default"))
+                                      ".com/compute/v1beta15/projects/myproject/global/networks/default"))
                               .build()
               )
               .addDisk(
@@ -65,11 +68,14 @@ public class ParseInstanceTest extends BaseGoogleComputeEngineParseTest<Instance
                               .mode(Instance.PersistentAttachedDisk.Mode.READ_WRITE)
                               .deviceName("test")
                               .source(URI.create("https://www.googleapis" +
-                                      ".com/compute/v1beta13/projects/myproject/disks/test"))
+                                      ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/test"))
                               .build()
               )
-              .addTag("aTag")
-              .metadata(ImmutableMap.of("aKey", "aValue"))
+              .tags(Instance.Tags.builder().fingerprint("abcd").addItem("aTag").build())
+              .metadata(Metadata.builder()
+                      .items(ImmutableMap.of("aKey", "aValue"))
+                      .fingerprint("efgh")
+                      .build())
               .addServiceAccount(Instance.ServiceAccount.builder().email("default").addScopes("myscope").build())
               .build();
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelListTest.java
index 67f7069..f95540d 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelListTest.java
@@ -16,17 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.googlecomputeengine.domain.Kernel;
-import org.jclouds.googlecomputeengine.domain.ListPage;
-import org.jclouds.googlecomputeengine.domain.Resource;
+import org.jclouds.googlecomputeengine.domain.*;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -44,15 +44,15 @@ public class ParseKernelListTest extends BaseGoogleComputeEngineParseTest<ListPa
    public ListPage<Kernel> expected() {
       return ListPage.<Kernel>builder()
               .kind(Resource.Kind.KERNEL_LIST)
-              .id("projects/google/kernels")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/kernels"))
+              .id("projects/google/global/kernels")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels"))
               .items(ImmutableSet.of(
                       Kernel.builder()
                               .id("12941177846308850718")
                               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
                                       ("2012-07-16T21:42:16.950"))
                               .selfLink(URI.create("https://www.googleapis" +
-                                      ".com/compute/v1beta13/projects/google/kernels/gce-20110524"))
+                                      ".com/compute/v1beta15/projects/google/global/kernels/gce-20110524"))
                               .name("gce-20110524")
                               .description("DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000").build(),
                       Kernel.builder()
@@ -60,9 +60,14 @@ public class ParseKernelListTest extends BaseGoogleComputeEngineParseTest<ListPa
                               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
                                       ("2012-07-16T21:42:31.166"))
                               .selfLink(URI.create("https://www.googleapis" +
-                                      ".com/compute/v1beta13/projects/google/kernels/gce-20110728"))
+                                      ".com/compute/v1beta15/projects/google/global/kernels/gce-20110728"))
                               .name("gce-20110728")
-                              .description("DEPRECATED. Created Thu, 28 Jul 2011 16:44:38 +0000").build()
+                              .description("DEPRECATED. Created Thu, 28 Jul 2011 16:44:38 +0000")
+                              .deprecated(org.jclouds.googlecomputeengine.domain.Deprecated.builder()
+                                      .state("OBSOLETE")
+                                      .replacement(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-v20130603"))
+                                      .build())
+                              .build()
               )).build();
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelTest.java
index b857d8b..84fdd89 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseKernelTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Kernel;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -42,7 +43,7 @@ public class ParseKernelTest extends BaseGoogleComputeEngineParseTest<Kernel> {
       return Kernel.builder()
               .id("12941177846308850718")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-07-16T21:42:16.950"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110524"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-20110524"))
               .name("gce-20110524")
               .description("DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000")
               .build();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeListTest.java
index 9804377..e854d6b 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeListTest.java
@@ -16,16 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.googlecomputeengine.domain.ListPage;
-import org.jclouds.googlecomputeengine.domain.MachineType;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import static org.jclouds.googlecomputeengine.domain.Resource.Kind.MACHINE_TYPE_LIST;
+
+import java.net.URI;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
-import java.net.URI;
 
-import static org.jclouds.googlecomputeengine.domain.Resource.Kind.MACHINE_TYPE_LIST;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
 /**
  * @author David Alves
@@ -45,12 +46,27 @@ public class ParseMachineTypeListTest extends BaseGoogleComputeEngineParseTest<L
       return ListPage.<MachineType>builder()
               .kind(MACHINE_TYPE_LIST)
               .id("projects/myproject/machineTypes")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes"))
+              .addItem(MachineType.builder()
+                      .id("4618642685664990776")
+                      .creationTimestamp(dateService.iso8601DateParse("2013-04-25T13:32:49.088-07:00"))
+                      .selfLink(URI.create("https://www.googleapis" +
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/f1-micro"))
+                      .zone("us-central1-a")
+                      .name("f1-micro")
+                      .description("1 vCPU (shared physical core) and 0.6 GB RAM")
+                      .guestCpus(1)
+                      .memoryMb(614)
+                      .imageSpaceGb(0)
+                      .maximumPersistentDisks(4)
+                      .maximumPersistentDisksSizeGb(3072)
+                      .build())
               .addItem(MachineType.builder()
                       .id("12907738072351752276")
                       .creationTimestamp(dateService.iso8601DateParse("2012-06-07T20:48:14.670"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1"))
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1"))
+                      .zone("us-central1-a")
                       .name("n1-standard-1")
                       .description("1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk")
                       .guestCpus(1)
@@ -63,15 +79,16 @@ public class ParseMachineTypeListTest extends BaseGoogleComputeEngineParseTest<L
                       .id("12908560709887590691")
                       .creationTimestamp(dateService.iso8601DateParse("2012-06-07T20:51:19.936"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-8-d"))
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-8-d"))
+                      .zone("us-central1-a")
                       .name("n1-standard-8-d")
                       .description("8 vCPUs, 30 GB RAM, a 10 GB ephemeral root disk, " +
                               "and 2 extra 1770 GB ephemeral disks")
                       .guestCpus(8)
                       .memoryMb(30720)
                       .imageSpaceGb(10)
-                      .addEphemeralDisk(1770)
-                      .addEphemeralDisk(1770)
+                      .addScratchDisk(1770)
+                      .addScratchDisk(1770)
                       .maximumPersistentDisks(16)
                       .maximumPersistentDisksSizeGb(1024)
                       .build())

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeTest.java
index b53c445..e55cd5c 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMachineTypeTest.java
@@ -16,13 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.googlecomputeengine.domain.MachineType;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import java.net.URI;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
-import java.net.URI;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
 /**
  * @author David Alves
@@ -42,15 +43,16 @@ public class ParseMachineTypeTest extends BaseGoogleComputeEngineParseTest<Machi
       return MachineType.builder()
               .id("12907738072351752276")
               .creationTimestamp(dateService.iso8601DateParse("2012-06-07T20:48:14.670"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1" +
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1" +
                       "-standard-1"))
+              .zone("us-central1-a")
               .name("n1-standard-1")
               .description("1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk")
               .guestCpus(1)
               .memoryMb(3840)
               .imageSpaceGb(10)
-              .addEphemeralDisk(1770)
-              .addEphemeralDisk(1770)
+              .addScratchDisk(1770)
+              .addScratchDisk(1770)
               .maximumPersistentDisks(16)
               .maximumPersistentDisksSizeGb(128)
               .build();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMetadataTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMetadataTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMetadataTest.java
index 52defb7..ebd5298 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMetadataTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseMetadataTest.java
@@ -16,19 +16,20 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableMap;
-import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecomputeengine.domain.Metadata;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * @author David Alves
  */
 @Test(groups = "unit")
-public class ParseMetadataTest extends BaseGoogleComputeEngineParseTest<GoogleComputeEngineParserModule.Metadata> {
+public class ParseMetadataTest extends BaseGoogleComputeEngineParseTest<Metadata> {
 
    @Override
    public String resource() {
@@ -37,8 +38,8 @@ public class ParseMetadataTest extends BaseGoogleComputeEngineParseTest<GoogleCo
 
    @Override
    @Consumes(MediaType.APPLICATION_JSON)
-   public GoogleComputeEngineParserModule.Metadata expected() {
-      return new GoogleComputeEngineParserModule.Metadata(
+   public Metadata expected() {
+      return new Metadata("efgh",
               ImmutableMap.<String, String>builder()
                       .put("propA", "valueA")
                       .put("propB", "valueB")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkListTest.java
index 1d2c78f..b271e91 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkListTest.java
@@ -16,15 +16,17 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Network;
 import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -42,7 +44,7 @@ public class ParseNetworkListTest extends BaseGoogleComputeEngineParseTest<ListP
       return ListPage.<Network>builder()
               .kind(Resource.Kind.NETWORK_LIST)
               .id("projects/myproject/networks")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/networks"))
               .items(ImmutableSet.of(new ParseNetworkTest().expected()))
               .build();
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkTest.java
index 4a4592a..da6992a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseNetworkTest.java
@@ -16,13 +16,14 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.googlecomputeengine.domain.Network;
-import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import java.net.URI;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.core.MediaType;
-import java.net.URI;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Network;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
 /**
  * @author David Alves
@@ -40,7 +41,7 @@ public class ParseNetworkTest extends BaseGoogleComputeEngineParseTest<Network>
       return Network.builder()
               .id("13024414170909937976")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-10-24T20:13:19.967"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/networks/jclouds-test"))
               .name("default")
               .description("Default network for the project")
               .IPv4Range("10.0.0.0/8")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationListTest.java
index d8e1e26..c62b49a 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationListTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Operation;
 import org.jclouds.googlecomputeengine.domain.Resource;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -32,7 +33,7 @@ public class ParseOperationListTest extends BaseGoogleComputeEngineParseTest<Lis
 
    @Override
    public String resource() {
-      return "/operation_list.json";
+      return "/global_operation_list.json";
    }
 
    @Override
@@ -40,8 +41,8 @@ public class ParseOperationListTest extends BaseGoogleComputeEngineParseTest<Lis
    public ListPage<Operation> expected() {
       return ListPage.<Operation>builder()
               .kind(Resource.Kind.OPERATION_LIST)
-              .id("projects/myproject/operations")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/operations"))
+              .id("projects/myproject/global/operations")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/operations"))
               .addItem(new ParseOperationTest().expected())
               .build();
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationTest.java
index 0813038..c3b1e90 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseOperationTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Operation;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -33,7 +34,7 @@ public class ParseOperationTest extends BaseGoogleComputeEngineParseTest<Operati
 
    @Override
    public String resource() {
-      return "/operation.json";
+      return "/global_operation.json";
    }
 
    @Override
@@ -42,12 +43,11 @@ public class ParseOperationTest extends BaseGoogleComputeEngineParseTest<Operati
       SimpleDateFormatDateService dateService = new SimpleDateFormatDateService();
       return Operation.builder().id("13053095055850848306")
               .selfLink(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8" +
+                      ".com/compute/v1beta15/projects/myproject/global/operations/operation-1354084865060-4cf88735faeb8" +
                       "-bbbb12cb"))
               .name("operation-1354084865060-4cf88735faeb8-bbbb12cb")
               .targetLink(URI.create("https://www.googleapis" +
-                      ".com/compute/v1beta13/projects/myproject/instances/instance-api-live" +
-                      "-test-instance"))
+                      ".com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test-delete"))
               .targetId("13053094017547040099")
               .status(Operation.Status.DONE)
               .user("user@developer.gserviceaccount.com")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseProjectTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseProjectTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseProjectTest.java
index 5d0c173..76acc08 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseProjectTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseProjectTest.java
@@ -16,15 +16,18 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableMap;
+import java.net.URI;
+import java.util.Date;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecomputeengine.domain.Metadata;
 import org.jclouds.googlecomputeengine.domain.Project;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-import java.util.Date;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * @author David Alves
@@ -43,14 +46,16 @@ public class ParseProjectTest extends BaseGoogleComputeEngineParseTest<Project>
       return Project.builder()
               .id("13024414184846275913")
               .creationTimestamp(new Date(Long.parseLong("1351109596252")))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject"))
               .name("myproject")
               .description("")
-              .commonInstanceMetadata(
-                      ImmutableMap.<String, String>builder()
+              .commonInstanceMetadata(Metadata.builder()
+                      .items(ImmutableMap.<String, String>builder()
                               .put("propA", "valueA")
                               .put("propB", "valueB")
                               .build())
+                      .fingerprint("efgh")
+                      .build())
               .addQuota("INSTANCES", 0, 8)
               .addQuota("CPUS", 0, 8)
               .addQuota("EPHEMERAL_ADDRESSES", 0, 8)


[02/11] JCLOUDS-209. Move to GCE v1beta15 API, with new features/methods included

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseQuotaTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseQuotaTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseQuotaTest.java
index 3bc72bd..110e49c 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseQuotaTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseQuotaTest.java
@@ -16,13 +16,13 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.googlecomputeengine.domain.Project;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-
 /**
  * @author David Alves
  */

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionListTest.java
new file mode 100644
index 0000000..cdbf67c
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionListTest.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.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Region;
+import org.jclouds.googlecomputeengine.domain.Resource;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class ParseRegionListTest extends BaseGoogleComputeEngineParseTest<ListPage<Region>> {
+
+   @Override
+   public String resource() {
+      return "/region_list.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public ListPage<Region> expected() {
+      return ListPage.<Region>builder()
+              .kind(Resource.Kind.REGION_LIST)
+              .id("projects/myproject/regions")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions"))
+              .items(ImmutableSet.of(
+                      new ParseRegionTest().expected(),
+                      Region.builder()
+                              .id("6396763663251190992")
+                              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
+                                      ("2013-07-08T14:40:37.939-07:00"))
+                              .selfLink(URI.create("https://www.googleapis" +
+                                      ".com/compute/v1beta15/projects/myproject/regions/us-central2"))
+                              .name("us-central2")
+                              .description("us-central2")
+                              .status(Region.Status.UP)
+                              .zone(URI.create("https://www.googleapis.com/compute/v1beta15/zones/us-central2-a"))
+                              .build()))
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionTest.java
new file mode 100644
index 0000000..746e51d
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRegionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Region;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class ParseRegionTest extends BaseGoogleComputeEngineParseTest<Region> {
+
+   @Override
+   public String resource() {
+      return "/region_get.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Region expected() {
+      return Region.builder()
+              .id("12912210600542709766")
+              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-08T14:40:37.939-07:00"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1"))
+              .name("us-central1")
+              .description("us-central1")
+              .status(Region.Status.UP)
+              .zones(ImmutableSet.of(URI.create("https://www.googleapis.com/compute/v1beta15/zones/us-central1-a"),
+                      URI.create("https://www.googleapis.com/compute/v1beta15/zones/us-central1-b")))
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteListTest.java
new file mode 100644
index 0000000..b7544cf
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteListTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Resource.Kind;
+import org.jclouds.googlecomputeengine.domain.Route;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class ParseRouteListTest extends BaseGoogleComputeEngineParseTest<ListPage<Route>> {
+
+   @Override
+   public String resource() {
+      return "/route_list.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public ListPage<Route> expected() {
+      return ListPage.<Route>builder()
+              .kind(Kind.ROUTE_LIST)
+              .id("projects/myproject/global/routes")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes"))
+              .items(ImmutableSet.of(new ParseRouteTest().expected(),
+                      Route.builder()
+                              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-fc92a41ecb5a8d17"))
+                              .id("507025480040058551")
+                              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-08T14:40:38.502-07:00"))
+                              .name("default-route-fc92a41ecb5a8d17")
+                              .description("Default route to the Internet.")
+                              .network(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"))
+                              .destRange("0.0.0.0/0")
+                              .priority(1000)
+                              .nextHopGateway(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/gateways/default-internet-gateway"))
+                              .build())
+              ).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteTest.java
new file mode 100644
index 0000000..d7d6d71
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseRouteTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Route;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class ParseRouteTest extends BaseGoogleComputeEngineParseTest<Route> {
+
+   @Override
+   public String resource() {
+      return "/route_get.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Route expected() {
+      return Route.builder()
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/routes/default-route-c99ebfbed0e1f375"))
+              .id("7241926205630356071")
+              .name("default-route-c99ebfbed0e1f375")
+              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-08T14:40:38.502-07:00"))
+              .description("Default route to the virtual network.")
+              .network(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"))
+              .destRange("10.240.0.0/16")
+              .priority(1000)
+              .nextHopNetwork(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"))
+              .tags(ImmutableSet.of("fooTag", "barTag"))
+              .build();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotListTest.java
new file mode 100644
index 0000000..cc93a6b
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotListTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.ListPage;
+import org.jclouds.googlecomputeengine.domain.Resource.Kind;
+import org.jclouds.googlecomputeengine.domain.Snapshot;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit")
+public class ParseSnapshotListTest extends BaseGoogleComputeEngineParseTest<ListPage<Snapshot>> {
+
+   @Override
+   public String resource() {
+      return "/snapshot_list.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public ListPage<Snapshot> expected() {
+      return ListPage.<Snapshot>builder()
+              .kind(Kind.SNAPSHOT_LIST)
+              .id("projects/myproject/global/snapshots")
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots"))
+              .items(ImmutableSet.of(
+                      new ParseSnapshotTest().expected(), Snapshot.builder()
+                      .selfLink(URI.create("https://www.googleapis" +
+                              ".com/compute/v1beta15/projects/myproject/global/snapshots/test-snap2"))
+                      .id("13895715048576107883")
+                      .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
+                              ("2013-07-26T12:57:01.927-07:00"))
+                      .status("READY")
+                      .sizeGb(10)
+                      .sourceDisk(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
+                      .name("test-snap2")
+                      .description("")
+                      .sourceDiskId("8243603669926824540")
+                      .build()))
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotTest.java
new file mode 100644
index 0000000..9c90255
--- /dev/null
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseSnapshotTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.googlecomputeengine.domain.Snapshot;
+import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author David Alves
+ */
+@Test(groups = "unit")
+public class ParseSnapshotTest extends BaseGoogleComputeEngineParseTest<Snapshot> {
+
+   @Override
+   public String resource() {
+      return "/snapshot_get.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public Snapshot expected() {
+      return Snapshot.builder()
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/global/snapshots/test-snap"))
+              .id("9734455566806191190")
+              .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2013-07-26T12:54:23.173-07:00"))
+              .status("READY")
+              .sizeGb(10)
+              .sourceDisk(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1"))
+              .name("test-snap")
+              .description("")
+              .sourceDiskId("8243603669926824540")
+              .build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneListTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneListTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneListTest.java
index 2dd7590..367cb63 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneListTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneListTest.java
@@ -16,7 +16,11 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
-import com.google.common.collect.ImmutableSet;
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.ListPage;
 import org.jclouds.googlecomputeengine.domain.Resource;
@@ -24,9 +28,7 @@ import org.jclouds.googlecomputeengine.domain.Zone;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author David Alves
@@ -45,7 +47,7 @@ public class ParseZoneListTest extends BaseGoogleComputeEngineParseTest<ListPage
       return ListPage.<Zone>builder()
               .kind(Resource.Kind.ZONE_LIST)
               .id("projects/myproject/zones")
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/zones"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones"))
               .items(ImmutableSet.of(
                       new ParseZoneTest().expected()
                       , Zone.builder()
@@ -53,9 +55,9 @@ public class ParseZoneListTest extends BaseGoogleComputeEngineParseTest<ListPage
                       .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
                               ("2012-10-24T20:13:19.271"))
                       .selfLink(URI.create("https://www.googleapis" +
-                              ".com/compute/v1beta13/projects/myproject/zones/us-east1-a"))
-                      .name("us-east1-a")
-                      .description("us-east1-a")
+                              ".com/compute/v1beta15/projects/myproject/zones/us-central1-b"))
+                      .name("us-central1-b")
+                      .description("us-central1-b")
                       .status(Zone.Status.UP)
                       .addMaintenanceWindow(Zone.MaintenanceWindow.builder()
                               .name("2013-02-17-planned-outage")

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneTest.java
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneTest.java b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneTest.java
index 105bd01..60a0b04 100644
--- a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneTest.java
+++ b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/parse/ParseZoneTest.java
@@ -16,15 +16,16 @@
  */
 package org.jclouds.googlecomputeengine.parse;
 
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.googlecomputeengine.domain.Zone;
 import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
 import org.testng.annotations.Test;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.core.MediaType;
-import java.net.URI;
-
 /**
  * @author David Alves
  */
@@ -42,7 +43,7 @@ public class ParseZoneTest extends BaseGoogleComputeEngineParseTest<Zone> {
       return Zone.builder()
               .id("13020128040171887099")
               .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-10-19T16:42:54.131"))
-              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
+              .selfLink(URI.create("https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a"))
               .name("us-central1-a")
               .description("us-central1-a")
               .status(Zone.Status.DOWN)

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/address_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/address_get.json b/google-compute-engine/src/test/resources/address_get.json
new file mode 100644
index 0000000..a80793c
--- /dev/null
+++ b/google-compute-engine/src/test/resources/address_get.json
@@ -0,0 +1,12 @@
+{
+
+    "kind": "compute#address",
+    "id": "4439373783165447583",
+    "creationTimestamp": "2013-07-26T13:57:20.204-07:00",
+    "status": "RESERVED",
+    "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+    "name": "test-ip1",
+    "description": "",
+    "address": "173.255.115.190",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/address_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/address_insert.json b/google-compute-engine/src/test/resources/address_insert.json
new file mode 100644
index 0000000..4bccf63
--- /dev/null
+++ b/google-compute-engine/src/test/resources/address_insert.json
@@ -0,0 +1 @@
+{"name":"test-ip1"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/address_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/address_list.json b/google-compute-engine/src/test/resources/address_list.json
new file mode 100644
index 0000000..78f2bce
--- /dev/null
+++ b/google-compute-engine/src/test/resources/address_list.json
@@ -0,0 +1,31 @@
+{
+    "kind": "compute#addressList",
+    "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses",
+    "id": "projects/myproject/regions/us-central1/addresses",
+    "items": [
+        {
+
+            "kind": "compute#address",
+            "id": "4439373783165447583",
+            "creationTimestamp": "2013-07-26T13:57:20.204-07:00",
+            "status": "RESERVED",
+            "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+            "name": "test-ip1",
+            "description": "",
+            "address": "173.255.115.190",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip1"
+        },
+        {
+
+            "kind": "compute#address",
+            "id": "4881363978908129158",
+            "creationTimestamp": "2013-07-26T14:08:21.552-07:00",
+            "status": "RESERVED",
+            "region": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1",
+            "name": "test-ip2",
+            "description": "",
+            "address": "173.255.118.115",
+            "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/regions/us-central1/addresses/test-ip2"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/disk_create_snapshot.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/disk_create_snapshot.json b/google-compute-engine/src/test/resources/disk_create_snapshot.json
new file mode 100644
index 0000000..6499744
--- /dev/null
+++ b/google-compute-engine/src/test/resources/disk_create_snapshot.json
@@ -0,0 +1 @@
+{"name":"test-snap"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/disk_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/disk_get.json b/google-compute-engine/src/test/resources/disk_get.json
index 5c7ce0c..4e351ce 100644
--- a/google-compute-engine/src/test/resources/disk_get.json
+++ b/google-compute-engine/src/test/resources/disk_get.json
@@ -1,10 +1,10 @@
 {
- "kind": "compute#disk",
- "id": "13050421646334304115",
- "creationTimestamp": "2012-11-25T01:38:48.306",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1",
- "name": "testimage1",
- "sizeGb": "1",
- "zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
- "status": "READY"
+   "kind": "compute#disk",
+   "id": "13050421646334304115",
+   "creationTimestamp": "2012-11-25T01:38:48.306",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+   "name": "testimage1",
+   "sizeGb": "1",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+   "status": "READY"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/disk_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/disk_insert.json b/google-compute-engine/src/test/resources/disk_insert.json
index 82522a7..8699cdd 100644
--- a/google-compute-engine/src/test/resources/disk_insert.json
+++ b/google-compute-engine/src/test/resources/disk_insert.json
@@ -1 +1 @@
-{"name":"testimage1","sizeGb":1,"zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a"}
\ No newline at end of file
+{"name":"testimage1","sizeGb":1}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/disk_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/disk_list.json b/google-compute-engine/src/test/resources/disk_list.json
index 8b09831..6836907 100644
--- a/google-compute-engine/src/test/resources/disk_list.json
+++ b/google-compute-engine/src/test/resources/disk_list.json
@@ -1,17 +1,17 @@
 {
- "kind": "compute#diskList",
- "id": "projects/myproject/disks",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/disks",
- "items": [
-  {
-   "kind": "compute#disk",
-   "id": "13050421646334304115",
-   "creationTimestamp": "2012-11-25T01:38:48.306",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1",
-   "name": "testimage1",
-   "sizeGb": "1",
-   "zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
-   "status": "READY"
-  }
- ]
+   "kind": "compute#diskList",
+   "id": "projects/myproject/zones/us-central1-a/disks",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks",
+   "items": [
+      {
+         "kind": "compute#disk",
+         "id": "13050421646334304115",
+         "creationTimestamp": "2012-11-25T01:38:48.306",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+         "name": "testimage1",
+         "sizeGb": "1",
+         "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+         "status": "READY"
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/firewall_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/firewall_get.json b/google-compute-engine/src/test/resources/firewall_get.json
index cb981dd..dbf4e90 100644
--- a/google-compute-engine/src/test/resources/firewall_get.json
+++ b/google-compute-engine/src/test/resources/firewall_get.json
@@ -1,30 +1,30 @@
 {
 
- "kind": "compute#firewall",
- "id": "12862241031274216284",
- "creationTimestamp": "2012-04-13T03:05:02.855",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test",
- "name": "jclouds-test",
- "description": "Internal traffic from default allowed",
- "network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
- "sourceRanges": [
-  "10.0.0.0/8"
- ],
- "allowed": [
-  {
-   "IPProtocol": "tcp",
-   "ports": [
-    "1-65535"
+   "kind": "compute#firewall",
+   "id": "12862241031274216284",
+   "creationTimestamp": "2012-04-13T03:05:02.855",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test",
+   "name": "jclouds-test",
+   "description": "Internal traffic from default allowed",
+   "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/jclouds-test",
+   "sourceRanges": [
+      "10.0.0.0/8"
+   ],
+   "allowed": [
+      {
+         "IPProtocol": "tcp",
+         "ports": [
+            "1-65535"
+         ]
+      },
+      {
+         "IPProtocol": "udp",
+         "ports": [
+            "1-65535"
+         ]
+      },
+      {
+         "IPProtocol": "icmp"
+      }
    ]
-  },
-  {
-   "IPProtocol": "udp",
-   "ports": [
-    "1-65535"
-   ]
-  },
-  {
-   "IPProtocol": "icmp"
-  }
- ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/firewall_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/firewall_insert.json b/google-compute-engine/src/test/resources/firewall_insert.json
index 0f6ddfa..b9d0a9a 100644
--- a/google-compute-engine/src/test/resources/firewall_insert.json
+++ b/google-compute-engine/src/test/resources/firewall_insert.json
@@ -1 +1 @@
-{"name":"%s","network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/%s","sourceRanges":[%s],"sourceTags":[%s],"targetTags":[%s],"allowed":[{"IPProtocol":"tcp","ports":[%s]}]}
\ No newline at end of file
+{"name":"%s","network":"https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/%s","sourceRanges":[%s],"sourceTags":[%s],"targetTags":[%s],"allowed":[{"IPProtocol":"tcp","ports":[%s]}]}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/firewall_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/firewall_list.json b/google-compute-engine/src/test/resources/firewall_list.json
index 3bb1b22..6fe7da8 100644
--- a/google-compute-engine/src/test/resources/firewall_list.json
+++ b/google-compute-engine/src/test/resources/firewall_list.json
@@ -1,58 +1,58 @@
 {
- "kind": "compute#firewallList",
- "id": "projects/google/firewalls",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/firewalls",
- "items": [
-  {
+   "kind": "compute#firewallList",
+   "id": "projects/google/firewalls",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/firewalls",
+   "items": [
+      {
 
-   "kind": "compute#firewall",
-   "id": "12862241031274216284",
-   "creationTimestamp": "2012-04-13T03:05:02.855",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test",
-   "name": "jclouds-test",
-   "description": "Internal traffic from default allowed",
-   "network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
-   "sourceRanges": [
-    "10.0.0.0/8"
-   ],
-   "allowed": [
-    {
-     "IPProtocol": "tcp",
-     "ports": [
-      "1-65535"
-     ]
-    },
-    {
-     "IPProtocol": "udp",
-     "ports": [
-      "1-65535"
-     ]
-    },
-    {
-     "IPProtocol": "icmp"
-    }
-   ]
-  },
-  {
+         "kind": "compute#firewall",
+         "id": "12862241031274216284",
+         "creationTimestamp": "2012-04-13T03:05:02.855",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test",
+         "name": "jclouds-test",
+         "description": "Internal traffic from default allowed",
+         "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/jclouds-test",
+         "sourceRanges": [
+            "10.0.0.0/8"
+         ],
+         "allowed": [
+            {
+               "IPProtocol": "tcp",
+               "ports": [
+                  "1-65535"
+               ]
+            },
+            {
+               "IPProtocol": "udp",
+               "ports": [
+                  "1-65535"
+               ]
+            },
+            {
+               "IPProtocol": "icmp"
+            }
+         ]
+      },
+      {
 
-   "kind": "compute#firewall",
-   "id": "12862241067393040785",
-   "creationTimestamp": "2012-04-13T03:05:04.365",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/firewalls/default-ssh",
-   "name": "default-ssh",
-   "description": "SSH allowed from anywhere",
-   "network": "https://www.googleapis.com/compute/v1beta13/projects/google/networks/default",
-   "sourceRanges": [
-    "0.0.0.0/0"
-   ],
-   "allowed": [
-    {
-     "IPProtocol": "tcp",
-     "ports": [
-      "22"
-     ]
-    }
+         "kind": "compute#firewall",
+         "id": "12862241067393040785",
+         "creationTimestamp": "2012-04-13T03:05:04.365",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/firewalls/default-ssh",
+         "name": "default-ssh",
+         "description": "SSH allowed from anywhere",
+         "network": "https://www.googleapis.com/compute/v1beta15/projects/google/global/networks/default",
+         "sourceRanges": [
+            "0.0.0.0/0"
+         ],
+         "allowed": [
+            {
+               "IPProtocol": "tcp",
+               "ports": [
+                  "22"
+               ]
+            }
+         ]
+      }
    ]
-  }
- ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/global_operation.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/global_operation.json b/google-compute-engine/src/test/resources/global_operation.json
new file mode 100644
index 0000000..c949699
--- /dev/null
+++ b/google-compute-engine/src/test/resources/global_operation.json
@@ -0,0 +1,15 @@
+{
+   "kind": "compute#operation",
+   "id": "13053095055850848306",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+   "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test-delete",
+   "targetId": "13053094017547040099",
+   "status": "DONE",
+   "user": "user@developer.gserviceaccount.com",
+   "progress": 100,
+   "insertTime": "2012-11-28T06:41:05.060",
+   "startTime": "2012-11-28T06:41:05.142",
+   "endTime": "2012-11-28T06:41:06.142",
+   "operationType": "insert"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/global_operation_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/global_operation_list.json b/google-compute-engine/src/test/resources/global_operation_list.json
new file mode 100644
index 0000000..f3c6ecd
--- /dev/null
+++ b/google-compute-engine/src/test/resources/global_operation_list.json
@@ -0,0 +1,22 @@
+{
+   "kind": "compute#operationList",
+   "id": "projects/myproject/global/operations",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/operations",
+   "items": [
+      {
+         "kind": "compute#operation",
+         "id": "13053095055850848306",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
+         "targetLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/firewalls/jclouds-test-delete",
+         "targetId": "13053094017547040099",
+         "status": "DONE",
+         "user": "user@developer.gserviceaccount.com",
+         "progress": 100,
+         "insertTime": "2012-11-28T06:41:05.060",
+         "startTime": "2012-11-28T06:41:05.142",
+         "endTime": "2012-11-28T06:41:06.142",
+         "operationType": "insert"
+      }
+   ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_get.json b/google-compute-engine/src/test/resources/image_get.json
index 79d358e..eaadc4e 100644
--- a/google-compute-engine/src/test/resources/image_get.json
+++ b/google-compute-engine/src/test/resources/image_get.json
@@ -1,14 +1,14 @@
 {
- "kind": "compute#image",
- "id": "12941197498378735318",
- "creationTimestamp": "2012-07-16T22:16:13.468",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326",
- "name": "centos-6-2-v20120326",
- "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
- "sourceType": "RAW",
- "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326",
- "rawDisk": {
-  "source": "",
-  "containerType": "TAR"
- }
-}
\ No newline at end of file
+   "kind": "compute#image",
+   "id": "12941197498378735318",
+   "creationTimestamp": "2012-07-16T22:16:13.468",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326",
+   "name": "centos-6-2-v20120326",
+   "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
+   "sourceType": "RAW",
+   "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120326",
+   "rawDisk": {
+      "source": "",
+      "containerType": "TAR"
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_insert.json b/google-compute-engine/src/test/resources/image_insert.json
index 787ffde..fd030a7 100644
--- a/google-compute-engine/src/test/resources/image_insert.json
+++ b/google-compute-engine/src/test/resources/image_insert.json
@@ -1 +1,4 @@
-{"sourceType":"RAW","rawDisk":{"source":"https://storage.googleapis.com/mybuket/myimage.image.tar.gz","containerType":"TAR"},"kind":"compute#image","name":"myimage"}
\ No newline at end of file
+{"sourceType": "RAW", "rawDisk": {
+   "source": "https://storage.googleapis.com/mybuket/myimage.image.tar.gz",
+   "containerType": "TAR"
+}, "kind": "compute#image", "name": "myimage"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_list.json b/google-compute-engine/src/test/resources/image_list.json
index 6095b29..cb76533 100644
--- a/google-compute-engine/src/test/resources/image_list.json
+++ b/google-compute-engine/src/test/resources/image_list.json
@@ -1,21 +1,25 @@
 {
- "kind": "compute#imageList",
- "id": "projects/google/images",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images",
- "items": [
-  {
-   "kind": "compute#image",
-   "id": "12941197498378735318",
-   "creationTimestamp": "2012-07-16T22:16:13.468",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326",
-   "name": "centos-6-2-v20120326",
-   "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  }
-  ]
-}
\ No newline at end of file
+   "kind": "compute#imageList",
+   "id": "projects/google/global/images",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images",
+   "items": [
+      {
+         "kind": "compute#image",
+         "id": "12941197498378735318",
+         "creationTimestamp": "2012-07-16T22:16:13.468",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326",
+         "name": "centos-6-2-v20120326",
+         "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120326",
+         "deprecated": {
+            "state": "DEPRECATED",
+            "replacement": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-v20130104"
+         },
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      }
+   ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_list_multiple_page_1.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_list_multiple_page_1.json b/google-compute-engine/src/test/resources/image_list_multiple_page_1.json
index afb794c..950613d 100644
--- a/google-compute-engine/src/test/resources/image_list_multiple_page_1.json
+++ b/google-compute-engine/src/test/resources/image_list_multiple_page_1.json
@@ -1,50 +1,58 @@
 {
- "kind": "compute#imageList",
- "id": "projects/google/images",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images",
- "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx",
- "items": [
-   {
-    "kind": "compute#image",
-    "id": "12941197498378735318",
-    "creationTimestamp": "2012-07-16T15:16:13.468-07:00",
-    "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326",
-    "name": "centos-6-2-v20120326",
-    "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
-    "sourceType": "RAW",
-    "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326",
-    "rawDisk": {
-     "source": "",
-     "containerType": "TAR"
-    }
-   },
-   {
-    "kind": "compute#image",
-    "id": "12894486577628239762",
-    "creationTimestamp": "2012-05-21T13:15:37.215-07:00",
-    "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120503",
-    "name": "centos-6-2-v20120503",
-    "description": "CentOS 6.2; Created Wed, 09 May 2012 11:55:54 +0000",
-    "sourceType": "RAW",
-    "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326",
-    "rawDisk": {
-     "source": "",
-     "containerType": "TAR"
-    }
-   },
-   {
-    "kind": "compute#image",
-    "id": "12917726455664967299",
-    "creationTimestamp": "2012-06-18T11:05:30.664-07:00",
-    "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120611",
-    "name": "centos-6-2-v20120611",
-    "description": "CentOS 6.2; Created Mon, 11 Jun 2012 13:15:44 +0000",
-    "sourceType": "RAW",
-    "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120611",
-    "rawDisk": {
-     "source": "",
-     "containerType": "TAR"
-    }
-   }
- ]
-}
\ No newline at end of file
+   "kind": "compute#imageList",
+   "id": "projects/google/global/images",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images",
+   "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx",
+   "items": [
+      {
+         "kind": "compute#image",
+         "id": "12941197498378735318",
+         "creationTimestamp": "2012-07-16T15:16:13.468-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120326",
+         "name": "centos-6-2-v20120326",
+         "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120326",
+         "deprecated": {
+            "state": "DELETED",
+            "replacement": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-v20130104"
+         },
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "12894486577628239762",
+         "creationTimestamp": "2012-05-21T13:15:37.215-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120503",
+         "name": "centos-6-2-v20120503",
+         "description": "CentOS 6.2; Created Wed, 09 May 2012 11:55:54 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120326",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "12917726455664967299",
+         "creationTimestamp": "2012-06-18T11:05:30.664-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120611",
+         "name": "centos-6-2-v20120611",
+         "description": "CentOS 6.2; Created Mon, 11 Jun 2012 13:15:44 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120611",
+         "deprecated": {
+            "state": "DEPRECATED",
+            "replacement": "https://www.googleapis.com/compute/v1beta15/projects/debian-cloud/global/images/debian-7-wheezy-20130509"
+         },
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      }
+   ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_list_multiple_page_2.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_list_multiple_page_2.json b/google-compute-engine/src/test/resources/image_list_multiple_page_2.json
index 71529d5..e489868 100644
--- a/google-compute-engine/src/test/resources/image_list_multiple_page_2.json
+++ b/google-compute-engine/src/test/resources/image_list_multiple_page_2.json
@@ -1,50 +1,50 @@
 {
- "kind": "compute#imageList",
- "id": "projects/google/images",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images",
- "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2",
- "items": [
-  {
-   "kind": "compute#image",
-   "id": "12920641029336858796",
-   "creationTimestamp": "2012-06-21T22:59:56.392-07:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120621",
-   "name": "centos-6-2-v20120621",
-   "description": "CentOS 6.2; Created Thu, 21 Jun 2012 14:22:21 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120621",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  },
-  {
-   "kind": "compute#image",
-   "id": "12994279803511049620",
-   "creationTimestamp": "2012-09-18T08:52:47.584-07:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-v20120912",
-   "name": "centos-6-v20120912",
-   "description": "CentOS 6; Created Wed, 12 Sep 2012 00:00:00 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20120912",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  },
-  {
-   "kind": "compute#image",
-   "id": "13037720516378381209",
-   "creationTimestamp": "2012-11-09T11:40:41.079-08:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-v20121106",
-   "name": "centos-6-v20121106",
-   "description": "SCSI-enabled CentOS 6; Created Tue, 06 Nov 2012 00:00:00 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  }
- ]
-}
\ No newline at end of file
+   "kind": "compute#imageList",
+   "id": "projects/google/global/images",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images",
+   "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2",
+   "items": [
+      {
+         "kind": "compute#image",
+         "id": "12920641029336858796",
+         "creationTimestamp": "2012-06-21T22:59:56.392-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-2-v20120621",
+         "name": "centos-6-2-v20120621",
+         "description": "CentOS 6.2; Created Thu, 21 Jun 2012 14:22:21 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20120621",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "12994279803511049620",
+         "creationTimestamp": "2012-09-18T08:52:47.584-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-v20120912",
+         "name": "centos-6-v20120912",
+         "description": "CentOS 6; Created Wed, 12 Sep 2012 00:00:00 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-v20120912",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "13037720516378381209",
+         "creationTimestamp": "2012-11-09T11:40:41.079-08:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/centos-6-v20121106",
+         "name": "centos-6-v20121106",
+         "description": "SCSI-enabled CentOS 6; Created Tue, 06 Nov 2012 00:00:00 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-v20121106",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      }
+   ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/image_list_single_page.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/image_list_single_page.json b/google-compute-engine/src/test/resources/image_list_single_page.json
index b28f9a6..ab11b0d 100644
--- a/google-compute-engine/src/test/resources/image_list_single_page.json
+++ b/google-compute-engine/src/test/resources/image_list_single_page.json
@@ -1,49 +1,53 @@
 {
- "kind": "compute#imageList",
- "id": "projects/google/images",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images",
- "items": [
-  {
-   "kind": "compute#image",
-   "id": "13037722963789596520",
-   "creationTimestamp": "2012-11-09T11:43:28.749-08:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-10-04-v20121106",
-   "name": "gcel-10-04-v20121106",
-   "description": "SCSI-enabled GCEL 10.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  },
-  {
-   "kind": "compute#image",
-   "id": "13037721421359523565",
-   "creationTimestamp": "2012-11-09T11:40:51.994-08:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106",
-   "name": "gcel-12-04-v20121106",
-   "description": "SCSI-enabled GCEL 12.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  },
-  {
-   "kind": "compute#image",
-   "id": "12941198995845323366",
-   "creationTimestamp": "2012-07-16T15:18:50.405-07:00",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/ubuntu-10-04-v20110728",
-   "name": "ubuntu-10-04-v20110728",
-   "description": "DEPRECATED. GCEL 10.04 LTS; Created Thu, 28 Jul 2011 16:45:51 +0000",
-   "sourceType": "RAW",
-   "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110728",
-   "rawDisk": {
-    "source": "",
-    "containerType": "TAR"
-   }
-  }
- ]
-}
\ No newline at end of file
+   "kind": "compute#imageList",
+   "id": "projects/google/global/images",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images",
+   "items": [
+      {
+         "kind": "compute#image",
+         "id": "13037722963789596520",
+         "creationTimestamp": "2012-11-09T11:43:28.749-08:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-10-04-v20121106",
+         "name": "gcel-10-04-v20121106",
+         "description": "SCSI-enabled GCEL 10.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-v20121106",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "13037721421359523565",
+         "creationTimestamp": "2012-11-09T11:40:51.994-08:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106",
+         "name": "gcel-12-04-v20121106",
+         "description": "SCSI-enabled GCEL 12.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-v20121106",
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      },
+      {
+         "kind": "compute#image",
+         "id": "12941198995845323366",
+         "creationTimestamp": "2012-07-16T15:18:50.405-07:00",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/ubuntu-10-04-v20110728",
+         "name": "ubuntu-10-04-v20110728",
+         "description": "DEPRECATED. GCEL 10.04 LTS; Created Thu, 28 Jul 2011 16:45:51 +0000",
+         "sourceType": "RAW",
+         "preferredKernel": "https://www.googleapis.com/compute/v1beta15/projects/google/kernels/gce-20110728",
+         "deprecated": {
+            "state": "DELETED",
+            "replacement": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-10-04-v20130104"
+         },
+         "rawDisk": {
+            "source": "",
+            "containerType": "TAR"
+         }
+      }
+   ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_add_access_config.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_add_access_config.json b/google-compute-engine/src/test/resources/instance_add_access_config.json
index 7530a7e..8edaf8a 100644
--- a/google-compute-engine/src/test/resources/instance_add_access_config.json
+++ b/google-compute-engine/src/test/resources/instance_add_access_config.json
@@ -1,11 +1,11 @@
-POST https://www.googleapis.com/compute/v1beta13/projects/jclouds-gce/instances/test-instance/addAccessConfig?network_interface=nic0&key={YOUR_API_KEY}
+POST https://www.googleapis.com/compute/v1beta15/projects/jclouds-gce/zones/us-central1-a/instances/test-instance/addAccessConfig?network_interface=nic0&key={YOUR_API_KEY}
 
 Content-Type:  application/json
 Authorization:  Bearer ya29.AHES6ZRyNKVHwnMPUvZitAuA8mR8b0lcWh1bMI5UQ5bgsJ4j
 X-JavaScript-User-Agent:  Google APIs Explorer
 
 {
- "name": "config1",
- "natIP": "10.0.1.1",
- "type": "ONE_TO_ONE_NAT"
+"name": "config1",
+"natIP": "10.0.1.1",
+"type": "ONE_TO_ONE_NAT"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_attach_disk.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_attach_disk.json b/google-compute-engine/src/test/resources/instance_attach_disk.json
new file mode 100644
index 0000000..0db3332
--- /dev/null
+++ b/google-compute-engine/src/test/resources/instance_attach_disk.json
@@ -0,0 +1,6 @@
+{
+    "type": "PERSISTENT",
+    "mode": "READ_ONLY",
+    "source": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/testimage1",
+    "boot": false
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_get.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_get.json b/google-compute-engine/src/test/resources/instance_get.json
index 19ca0c3..b3f3723 100644
--- a/google-compute-engine/src/test/resources/instance_get.json
+++ b/google-compute-engine/src/test/resources/instance_get.json
@@ -1,50 +1,54 @@
 {
- "kind": "compute#instance",
- "id": "13051190678907570425",
- "description": "desc",
- "creationTimestamp": "2012-11-25T23:48:20.758",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-0",
- "name": "test-0",
- "image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106",
- "machineType": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
- "status": "RUNNING",
- "zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
- "networkInterfaces": [
-  {
-    "kind": "compute#instanceNetworkInterface",
-    "name": "nic0",
-    "networkIP": "10.240.121.115",
-    "network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"
-  }
- ],
- "disks": [
-  {
-    "kind": "compute#instanceDisk",
-    "type": "PERSISTENT",
-    "mode": "READ_WRITE",
-    "deviceName": "test",
-    "source": "https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test",
-    "index": 0
-  }
- ],
- "serviceAccounts": [
-  {
-    "kind": "compute#serviceAccount",
-    "email": "default",
-    "scopes": [
-      "myscope"
-    ]
-  }
- ],
- "metadata": {
-   "items": [
-     {
-       "key": "aKey",
-       "value": "aValue"
-     }
-   ]
- },
- "tags": [
-     "aTag"
- ]
-}
\ No newline at end of file
+   "kind": "compute#instance",
+   "id": "13051190678907570425",
+   "description": "desc",
+   "creationTimestamp": "2012-11-25T23:48:20.758",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-0",
+   "name": "test-0",
+   "image": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106",
+   "machineType": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1",
+   "status": "RUNNING",
+   "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+   "networkInterfaces": [
+      {
+         "kind": "compute#instanceNetworkInterface",
+         "name": "nic0",
+         "networkIP": "10.240.121.115",
+         "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"
+      }
+   ],
+   "disks": [
+      {
+         "kind": "compute#instanceDisk",
+         "type": "PERSISTENT",
+         "mode": "READ_WRITE",
+         "deviceName": "test",
+         "source": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/test",
+         "index": 0
+      }
+   ],
+   "serviceAccounts": [
+      {
+         "kind": "compute#serviceAccount",
+         "email": "default",
+         "scopes": [
+            "myscope"
+         ]
+      }
+   ],
+   "metadata": {
+      "items": [
+         {
+            "key": "aKey",
+            "value": "aValue"
+         }
+      ],
+      "fingerprint": "efgh"
+   },
+   "tags": {
+      "items": [
+         "aTag"
+      ],
+      "fingerprint": "abcd"
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_insert.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_insert.json b/google-compute-engine/src/test/resources/instance_insert.json
index 6ec1efb..f626082 100644
--- a/google-compute-engine/src/test/resources/instance_insert.json
+++ b/google-compute-engine/src/test/resources/instance_insert.json
@@ -1 +1 @@
-{"name":"test-0","description":"desc","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","image":"https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106","tags":["aTag"],"serviceAccounts":[{"email":"default","scopes":["myscope"]}],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[{"type":"ONE_TO_ONE_NAT"}]}],"disks":[{"mode":"READ_WRITE","source":"https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test","type":"PERSISTENT"}],"metadata":{"kind":"compute#metadata","items":[{"key":"aKey","value":"aValue"}]}}
\ No newline at end of file
+{"name":"test-0","description":"desc","machineType":"https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1","image":"https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106","serviceAccounts":[{"email":"default","scopes":["myscope"]}],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default","accessConfigs":[{"type":"ONE_TO_ONE_NAT"}]}],"disks":[{"mode":"READ_WRITE","source":"https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/test","type":"PERSISTENT"}],"metadata":{"kind":"compute#metadata","items":[{"key":"aKey","value":"aValue"}]}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_insert_simple.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_insert_simple.json b/google-compute-engine/src/test/resources/instance_insert_simple.json
index 78b3e05..83b2b7a 100644
--- a/google-compute-engine/src/test/resources/instance_insert_simple.json
+++ b/google-compute-engine/src/test/resources/instance_insert_simple.json
@@ -1 +1 @@
-{"name":"test-1","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","tags":[],"serviceAccounts":[],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[]}]}
\ No newline at end of file
+{"name":"test-1","machineType":"https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1","image":"https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106","serviceAccounts":[],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default","accessConfigs":[]}]}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_list.json b/google-compute-engine/src/test/resources/instance_list.json
index fb3db8b..a66fa92 100644
--- a/google-compute-engine/src/test/resources/instance_list.json
+++ b/google-compute-engine/src/test/resources/instance_list.json
@@ -1,57 +1,61 @@
 {
- "kind": "compute#instanceList",
- "id": "projects/myproject/instances",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances",
- "items": [
-{
- "kind": "compute#instance",
- "id": "13051190678907570425",
- "description": "desc",
- "creationTimestamp": "2012-11-25T23:48:20.758",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-0",
- "name": "test-0",
- "image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106",
- "machineType": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
- "status": "RUNNING",
- "zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",
- "networkInterfaces": [
-  {
-    "kind": "compute#instanceNetworkInterface",
-    "name": "nic0",
-    "networkIP": "10.240.121.115",
-    "network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"
-  }
- ],
- "disks": [
-  {
-    "kind": "compute#instanceDisk",
-    "type": "PERSISTENT",
-    "mode": "READ_WRITE",
-    "deviceName": "test",
-    "source": "https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test",
-    "index": 0
-  }
- ],
- "serviceAccounts": [
-  {
-    "kind": "compute#serviceAccount",
-    "email": "default",
-    "scopes": [
-      "myscope"
-    ]
-  }
- ],
- "metadata": {
+   "kind": "compute#instanceList",
+   "id": "projects/myproject/zones/us-central1-a/instances",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances",
    "items": [
-     {
-       "key": "aKey",
-       "value": "aValue"
-     }
+      {
+         "kind": "compute#instance",
+         "id": "13051190678907570425",
+         "description": "desc",
+         "creationTimestamp": "2012-11-25T23:48:20.758",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/instances/test-0",
+         "name": "test-0",
+         "image": "https://www.googleapis.com/compute/v1beta15/projects/google/global/images/gcel-12-04-v20121106",
+         "machineType": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1",
+         "status": "RUNNING",
+         "zone": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a",
+         "networkInterfaces": [
+            {
+               "kind": "compute#instanceNetworkInterface",
+               "name": "nic0",
+               "networkIP": "10.240.121.115",
+               "network": "https://www.googleapis.com/compute/v1beta15/projects/myproject/global/networks/default"
+            }
+         ],
+         "disks": [
+            {
+               "kind": "compute#instanceDisk",
+               "type": "PERSISTENT",
+               "mode": "READ_WRITE",
+               "deviceName": "test",
+               "source": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/disks/test",
+               "index": 0
+            }
+         ],
+         "serviceAccounts": [
+            {
+               "kind": "compute#serviceAccount",
+               "email": "default",
+               "scopes": [
+                  "myscope"
+               ]
+            }
+         ],
+         "metadata": {
+            "items": [
+               {
+                  "key": "aKey",
+                  "value": "aValue"
+               }
+            ],
+            "fingerprint": "efgh"
+         },
+         "tags": {
+            "items": [
+               "aTag"
+            ],
+            "fingerprint": "abcd"
+         }
+      }
    ]
- },
- "tags": [
-     "aTag"
- ]
- }
- ]
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_list_central1b_empty.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_list_central1b_empty.json b/google-compute-engine/src/test/resources/instance_list_central1b_empty.json
new file mode 100644
index 0000000..dcdc609
--- /dev/null
+++ b/google-compute-engine/src/test/resources/instance_list_central1b_empty.json
@@ -0,0 +1,6 @@
+{
+   "kind": "compute#instanceList",
+   "id": "projects/myproject/zones/us-central1-b/instances",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-b/instances",
+   "items": [ ]
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_serial_port.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_serial_port.json b/google-compute-engine/src/test/resources/instance_serial_port.json
index 5813ce9..03280cc 100644
--- a/google-compute-engine/src/test/resources/instance_serial_port.json
+++ b/google-compute-engine/src/test/resources/instance_serial_port.json
@@ -1,4 +1,4 @@
 {
- "kind": "compute#serialPortOutput",
- "contents": "console output"
+   "kind": "compute#serialPortOutput",
+   "contents": "console output"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/instance_set_metadata.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/instance_set_metadata.json b/google-compute-engine/src/test/resources/instance_set_metadata.json
new file mode 100644
index 0000000..b39e983
--- /dev/null
+++ b/google-compute-engine/src/test/resources/instance_set_metadata.json
@@ -0,0 +1,10 @@
+{
+    "items": [
+        {
+            "key": "foo",
+            "value": "bar"
+        }
+    ],
+    "fingerprint": "efgh",
+    "kind": "compute#metadata"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/kernel.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/kernel.json b/google-compute-engine/src/test/resources/kernel.json
index a30b7a7..e304e08 100644
--- a/google-compute-engine/src/test/resources/kernel.json
+++ b/google-compute-engine/src/test/resources/kernel.json
@@ -1,8 +1,8 @@
 {
- "kind": "compute#kernel",
- "id": "12941177846308850718",
- "creationTimestamp": "2012-07-16T21:42:16.950",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110524",
- "name": "gce-20110524",
- "description": "DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000"
+   "kind": "compute#kernel",
+   "id": "12941177846308850718",
+   "creationTimestamp": "2012-07-16T21:42:16.950",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-20110524",
+   "name": "gce-20110524",
+   "description": "DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/kernel_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/kernel_list.json b/google-compute-engine/src/test/resources/kernel_list.json
index 7c5ce61..7fd4343 100644
--- a/google-compute-engine/src/test/resources/kernel_list.json
+++ b/google-compute-engine/src/test/resources/kernel_list.json
@@ -1,23 +1,27 @@
 {
- "kind": "compute#kernelList",
- "id": "projects/google/kernels",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels",
- "items": [
-  {
-   "kind": "compute#kernel",
-   "id": "12941177846308850718",
-   "creationTimestamp": "2012-07-16T21:42:16.950",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110524",
-   "name": "gce-20110524",
-   "description": "DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000"
-  },
-  {
-   "kind": "compute#kernel",
-   "id": "12941177983348179280",
-   "creationTimestamp": "2012-07-16T21:42:31.166",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110728",
-   "name": "gce-20110728",
-   "description": "DEPRECATED. Created Thu, 28 Jul 2011 16:44:38 +0000"
-  }
- ]
+   "kind": "compute#kernelList",
+   "id": "projects/google/global/kernels",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels",
+   "items": [
+      {
+          "kind": "compute#kernel",
+          "id": "12941177846308850718",
+          "creationTimestamp": "2012-07-16T21:42:16.950",
+          "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-20110524",
+          "name": "gce-20110524",
+          "description": "DEPRECATED. Created Tue, 24 May 2011 00:48:22 +0000"
+      },
+      {
+         "kind": "compute#kernel",
+         "id": "12941177983348179280",
+         "creationTimestamp": "2012-07-16T21:42:31.166",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-20110728",
+         "name": "gce-20110728",
+         "description": "DEPRECATED. Created Thu, 28 Jul 2011 16:44:38 +0000",
+          "deprecated": {
+              "state": "OBSOLETE",
+              "replacement": "https://www.googleapis.com/compute/v1beta15/projects/google/global/kernels/gce-v20130603"
+          }
+      }
+   ]
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/logback.xml b/google-compute-engine/src/test/resources/logback.xml
index 6bd571e..864a5a5 100644
--- a/google-compute-engine/src/test/resources/logback.xml
+++ b/google-compute-engine/src/test/resources/logback.xml
@@ -34,23 +34,50 @@
         </encoder>
     </appender>
 
+    <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-compute.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-ssh.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
     <root>
-        <level value="warn"/>
+        <level value="warn" />
     </root>
 
     <logger name="org.jclouds">
-        <level value="DEBUG"/>
-        <appender-ref ref="FILE"/>
+        <level value="TRACE" />
+        <appender-ref ref="FILE" />
     </logger>
 
     <logger name="jclouds.wire">
-        <level value="DEBUG"/>
-        <appender-ref ref="WIREFILE"/>
+        <level value="TRACE" />
+        <appender-ref ref="WIREFILE" />
     </logger>
 
     <logger name="jclouds.headers">
-        <level value="DEBUG"/>
-        <appender-ref ref="WIREFILE"/>
+        <level value="TRACE" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <logger name="jclouds.compute">
+        <level value="TRACE" />
+        <appender-ref ref="COMPUTEFILE" />
+    </logger>
+
+    <logger name="jclouds.ssh">
+        <level value="TRACE" />
+        <appender-ref ref="SSHFILE" />
     </logger>
 
 </configuration>
+

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/machinetype.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/machinetype.json b/google-compute-engine/src/test/resources/machinetype.json
index 6f22572..5aa902a 100644
--- a/google-compute-engine/src/test/resources/machinetype.json
+++ b/google-compute-engine/src/test/resources/machinetype.json
@@ -1,21 +1,22 @@
 {
- "kind": "compute#machineType",
- "id": "12907738072351752276",
- "creationTimestamp": "2012-06-07T20:48:14.670",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
- "name": "n1-standard-1",
- "description": "1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk",
- "guestCpus": 1,
- "memoryMb": 3840,
- "imageSpaceGb": 10,
- "ephemeralDisks": [
-     {
-      "diskGb": 1770
-     },
-     {
-      "diskGb": 1770
-     }
-    ],
- "maximumPersistentDisks": 16,
- "maximumPersistentDisksSizeGb": "128"
+   "kind": "compute#machineType",
+   "id": "12907738072351752276",
+   "creationTimestamp": "2012-06-07T20:48:14.670",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1",
+   "name": "n1-standard-1",
+   "description": "1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk",
+   "guestCpus": 1,
+   "memoryMb": 3840,
+   "imageSpaceGb": 10,
+   "scratchDisks": [
+      {
+         "diskGb": 1770
+      },
+      {
+         "diskGb": 1770
+      }
+   ],
+   "maximumPersistentDisks": 16,
+   "maximumPersistentDisksSizeGb": "128",
+   "zone": "us-central1-a"
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-google/blob/53386380/google-compute-engine/src/test/resources/machinetype_list.json
----------------------------------------------------------------------
diff --git a/google-compute-engine/src/test/resources/machinetype_list.json b/google-compute-engine/src/test/resources/machinetype_list.json
index 14e7318..0506a0e 100644
--- a/google-compute-engine/src/test/resources/machinetype_list.json
+++ b/google-compute-engine/src/test/resources/machinetype_list.json
@@ -1,41 +1,57 @@
 {
- "kind": "compute#machineTypeList",
- "id": "projects/myproject/machineTypes",
- "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes",
- "items": [
-  {
-   "kind": "compute#machineType",
-   "id": "12907738072351752276",
-   "creationTimestamp": "2012-06-07T20:48:14.670",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
-   "name": "n1-standard-1",
-   "description": "1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk",
-   "guestCpus": 1,
-   "memoryMb": 3840,
-   "imageSpaceGb": 10,
-   "maximumPersistentDisks": 16,
-   "maximumPersistentDisksSizeGb": "128"
-  },
-  {
-   "kind": "compute#machineType",
-   "id": "12908560709887590691",
-   "creationTimestamp": "2012-06-07T20:51:19.936",
-   "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-8-d",
-   "name": "n1-standard-8-d",
-   "description": "8 vCPUs, 30 GB RAM, a 10 GB ephemeral root disk, and 2 extra 1770 GB ephemeral disks",
-   "guestCpus": 8,
-   "memoryMb": 30720,
-   "imageSpaceGb": 10,
-   "ephemeralDisks": [
-    {
-     "diskGb": 1770
-    },
-    {
-     "diskGb": 1770
-    }
-   ],
-   "maximumPersistentDisks": 16,
-   "maximumPersistentDisksSizeGb": "1024"
-  }
- ]
+   "kind": "compute#machineTypeList",
+   "id": "projects/myproject/machineTypes",
+   "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes",
+   "items": [
+       {
+           "kind": "compute#machineType",
+           "id": "4618642685664990776",
+           "creationTimestamp": "2013-04-25T13:32:49.088-07:00",
+           "name": "f1-micro",
+           "description": "1 vCPU (shared physical core) and 0.6 GB RAM",
+           "guestCpus": 1,
+           "memoryMb": 614,
+           "imageSpaceGb": 0,
+           "maximumPersistentDisks": 4,
+           "maximumPersistentDisksSizeGb": "3072",
+           "zone": "us-central1-a",
+           "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/f1-micro"
+       },
+       {
+         "kind": "compute#machineType",
+         "id": "12907738072351752276",
+         "creationTimestamp": "2012-06-07T20:48:14.670",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-1",
+         "name": "n1-standard-1",
+         "description": "1 vCPU, 3.75 GB RAM, and a 10 GB ephemeral root disk",
+         "guestCpus": 1,
+         "memoryMb": 3840,
+         "imageSpaceGb": 10,
+         "maximumPersistentDisks": 16,
+         "maximumPersistentDisksSizeGb": "128",
+         "zone": "us-central1-a"
+      },
+      {
+         "kind": "compute#machineType",
+         "id": "12908560709887590691",
+         "creationTimestamp": "2012-06-07T20:51:19.936",
+         "selfLink": "https://www.googleapis.com/compute/v1beta15/projects/myproject/zones/us-central1-a/machineTypes/n1-standard-8-d",
+         "name": "n1-standard-8-d",
+         "description": "8 vCPUs, 30 GB RAM, a 10 GB ephemeral root disk, and 2 extra 1770 GB ephemeral disks",
+         "guestCpus": 8,
+         "memoryMb": 30720,
+         "imageSpaceGb": 10,
+         "scratchDisks": [
+            {
+               "diskGb": 1770
+            },
+            {
+               "diskGb": 1770
+            }
+         ],
+         "maximumPersistentDisks": 16,
+         "maximumPersistentDisksSizeGb": "1024",
+         "zone": "us-central1-a"
+      }
+   ]
 }
\ No newline at end of file