{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/comments/35496285","id":35496285,"diff_hunk":"@@ -0,0 +1,793 @@\n+/*!\n+ * Copyright 2014 Google Inc. All Rights Reserved.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *      http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+/*!\n+ * @module compute\n+ */\n+\n+'use strict';\n+\n+/**\n+ * @type {module:compute/region}\n+ * @private\n+ */\n+var Region = require('./region.js');\n+\n+/**\n+ * @type {module:compute/zone}\n+ * @private\n+ */\n+var Zone = require('./zone.js');\n+\n+/**\n+ * @type {module:compute/firewall}\n+ * @private\n+ */\n+var Firewall = require('./firewall.js');\n+\n+/**\n+ * @type {module:compute/snapshot}\n+ * @private\n+ */\n+var Snapshot = require('./snapshot.js');\n+\n+/**\n+ * @type {module:common/util}\n+ * @private\n+ */\n+var util = require('../common/util.js');\n+\n+/**\n+ * Required scopes for Google Compute Engine API.\n+ * @const {array}\n+ * @private\n+ */\n+var SCOPES = ['https://www.googleapis.com/auth/compute'];\n+\n+/**\n+ * @const {string}\n+ * @private\n+ */\n+var COMPUTE_BASE_URL = 'https://www.googleapis.com/compute/v1/projects/';\n+\n+/**\n+ * Create a Compute object to Interact with the Google Compute Engine API.\n+ * Using this object, you can access your instances with\n+ * {module:compute/instance}, disks with {module:compute/disk} and firewall\n+ * rules with {module:compute/firewall}.\n+ *\n+ * Follow along with the examples to see how to do everything. With a Compute\n+ * object it is possible to search for existing instances, disks and firewall\n+ * as well as to create new ones. Instances can be stopped, reset and started\n+ * and their tags can be updated. Disks can be deleted and attached to running\n+ * instances. Firewall rules can be created and updated.\n+ *\n+ * @alias module:compute\n+ * @constructor\n+ *\n+ * @param {object} options - [Configuration object](#/docs/?method=gcloud).\n+ *\n+ * @example\n+ * var gcloud = require('gcloud')({\n+ *   keyFilename: '/path/to/keyfile.json',\n+ *   projectId: 'grape-spaceship-123'\n+ * });\n+ *\n+ * var compute = gcloud.compute();\n+ */\n+function Compute(options) {\n+  if (!(this instanceof Compute)) {\n+    return new Compute(options);\n+  }\n+\n+  options = options || {};\n+\n+  this.makeAuthorizedRequest_ = util.makeAuthorizedRequestFactory({\n+    credentials: options.credentials,\n+    keyFile: options.keyFilename,\n+    scopes: SCOPES,\n+    email: options.email\n+  });\n+\n+  this.projectId = options.projectId;\n+}\n+\n+/**\n+ * Get a reference to a Google Compute Engine region.\n+ *\n+ * @param {string} name - Name of the region.\n+ * @return {module:compute/region}\n+ *\n+ * @example\n+ * var gcloud = require('gcloud')({\n+ *   keyFilename: '/path/to/keyfile.json'\n+ * });\n+ *\n+ * var compute = gcloud.compute();\n+ *\n+ * var myRegion = compute.region('region-name');\n+ */\n+Compute.prototype.region = function(name) {\n+  return new Region(this, name);\n+};\n+\n+/**\n+ * Get a reference to a Google Compute Engine zone.\n+ *\n+ * @param {string} name - Name of the zone.\n+ * @return {module:compute/zone}\n+ *\n+ * @example\n+ * var gcloud = require('gcloud')({\n+ *   keyFilename: '/path/to/keyfile.json'\n+ * });\n+ *\n+ * var compute = gcloud.compute();\n+ *\n+ * var myZone = compute.zone('zone-name');\n+ */\n+Compute.prototype.zone = function(name) {\n+  return new Zone(this, name);\n+};\n+\n+/**\n+ * Get a reference to a Google Compute Engine firewall.\n+ *\n+ * @param {string} name - Name of the existing firewall.\n+ * @param {string=} networkName - Network name for the existing firewall.\n+ *     Default value is 'global/networks/default'.\n+ * @return {module:compute/disk}\n+ *\n+ * @example\n+ * var gcloud = require('gcloud')({\n+ *   keyFilename: '/path/to/keyfile.json'\n+ * });\n+ *\n+ * var compute = gcloud.compute();\n+ *\n+ * var firewallRule = compute.firewall('rule1');\n+ */\n+Compute.prototype.firewall = function(name, networkName) {\n+  var options = {};\n+  options.networkName = networkName;\n+  return new Firewall(this, name, options);\n+};\n+\n+/**\n+ * Get a reference to a Google Compute Engine snapshot.\n+ *\n+ * @param {string} name - Name of the existing snapshot.\n+ * @return {module:compute/snapshot}\n+ *\n+ * @example\n+ * var gcloud = require('gcloud')({\n+ *   keyFilename: '/path/to/keyfile.json'\n+ * });\n+ *\n+ * var compute = gcloud.compute();\n+ *\n+ * var snapshot = compute.snapshot('snapshot-name');\n+ */\n+Compute.prototype.snapshot = function(name) {\n+  return new Snapshot(this, name);\n+};\n+\n+/**\n+ * Create a firewall rule.\n+ *\n+ * @throws {Error} if a firewall name or firewall options are not provided.\n+ *     If allowed ports, source tags or source ranges are not provided.\n+ *\n+ * @param {module:compute} compute - The Google Compute Engine instance this\n+ *     this firewall belongs to.\n+ * @param {string} name - Name of the firewall.\n+ * @param {object} options - Firewall options.\n+ * @param {string=} options.description - Description of the firewall.\n+ * @param {string=} options.network - Network to which the firewall applies.\n+ *     Default value is 'global/networks/default'.\n+ * @param {object[]=} options.allowed - List of allowed protocols and ports.\n+ * @param {string[]=} options.sourceRanges - IP address blocks to which this\n+ *     rule applies (in CIDR format).\n+ * @param {string[]=} options.sourceRanges - IP address blocks to which this\n+ *     rule applies (in CIDR format).\n+ * @param {string[]=} options.sourceTags - List of instance tags to which\n+ *     this rule applies.\n+ * @param {string[]=} options.targetTags - List of instance tags indicating\n+ *     instances that may process connections according to this rule.\n+ * @param {function} callback - The callback function.\n+ *\n+ * @example\n+ * var callback = function(err, firewall, apiResponse) {\n+ *   // `firewall` is a Firewall object.\n+ * };\n+ *\n+ * var compute = gcloud.compute({\n+ *   projectId: 'grape-spaceship-123'\n+ * });\n+ *\n+ * var firewall = compute.createFirewall('tcp-3000',\n+ *   {\n+ *     description: 'yada yada',\n+ *     allowed: [{\n+ *       IPProtocol: 'tcp',\n+ *       ports: ['3000']\n+ *     }],\n+ *     sourceRanges: ['0.0.0.0/0'],\n+ *     targetTags: ['tcp-3000-tag']\n+ *   }, callback);\n+ */\n+Compute.prototype.createFirewall = function(name, options, callback) {\n+  if (!name) {\n+    throw new Error('A name is needed to use a Compute Engine Firewall.');\n+  } else if (!/^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$/.test(name)) {\n+    throw new Error('Name must match [a-z]([-a-z0-9]{0,61}[a-z0-9])?');\n+  }\n+  if (!options || !util.is(options.allowed, 'array')) {\n+    throw new Error('Allowed protocols and ports must be provided.');\n+  }\n+  if (!util.is(options.sourceRanges, 'array') &&\n+    !util.is(options.sourceTags, 'array')) {\n+    throw new Error('Source ranges or source tags must be provided.');\n+  }\n+\n+  var body = {};\n+  body.name = name;\n+  if (util.is(options.description, 'string')) {\n+    body.description = options.description;\n+  }\n+  if (util.is(options.network, 'string')) {\n+    body.network = options.network;\n+  } else {\n+    body.network = 'global/networks/default';\n+  }\n+  if (util.is(options.allowed, 'array')) {\n+    body.allowed = options.allowed;\n+  }\n+  if (util.is(options.sourceRanges, 'array')) {\n+    body.sourceRanges = options.sourceRanges;\n+  }\n+  if (util.is(options.sourceTags, 'array')) {\n+    body.sourceTags = options.sourceTags;\n+  }\n+  if (util.is(options.targetTags, 'array')) {\n+    body.targetTags = options.targetTags;\n+  }\n+\n+  var self = this;\n+  this.makeReq_(\n+    'POST',\n+    '/global/firewalls',\n+    null,\n+    body, function(err, resp) {\n+      if (err) {\n+        callback(err);\n+        return;\n+      }\n+      var firewall = self.firewall(name);\n+      firewall.name = options;\n+      callback(null, firewall, resp);\n+    });\n+};\n+\n+/**\n+ * Get a list of instances.\n+ *\n+ * @throws {Error} if a malformed filter is provided.\n+ *\n+ * @param {object} options - Instance search options.\n+ * @param {number=} options.maxResults - Maximum number of instances to return.\n+ * @param {object=} options.filter - Search filter.\n+ * @param {string} options.filter.fieldName - Instance field to consider in this\n+ *     filter.\n+ * @param {string} options.filter.operatorString - Filter operator, can be\n+ *     either 'eq' or 'ne'.\n+ * @param {string} options.filter.literalString - String to compare the instance\n+ *     field to. Can be a regular expression.\n+ * @param {string=} pageToken - Page identifier used in paginated search.\n+ * @param {function} callback - The callback function.\n+ *\n+ * @example\n+ * var callback = function(err, instances) {\n+ *   // `instances` is an array of `Instance` objects.\n+ * };\n+ *\n+ * var compute = gcloud.compute({\n+ *   projectId: 'grape-spaceship-123'\n+ * });\n+ *\n+ * compute.getInstances(\n+ *   {\n+ *     filter: {\n+ *       fieldName : 'name',\n+ *       operatorString : 'eq',\n+ *       literalString : 'instance-[0-9]'\n+ *     }],\n+ *   }, callback);\n+ */\n+Compute.prototype.getInstances = function(options, callback) {\n+  if (util.is(options, 'function')) {\n+    callback = options;\n+    options = {};\n+  }\n+\n+  var query = {};\n+\n+  if (util.is(options.maxResults, 'number')) {\n+    query.maxResults = options.maxResults;\n+  }\n+  if (options.filter) {\n+    if (!util.is(options.filter.fieldName, 'string') ||\n+        !util.is(options.filter.operatorString, 'string') ||\n+        !util.is(options.filter.literalString, 'string')) {\n+      throw new Error(\n+        'A filter must have name, comparisonString and literal fields.');\n+    }\n+    if (options.filter.operatorString !== 'eq' &&\n+      options.filter.operatorString !== 'ne') {\n+      throw new Error('Filter operator must be either eq or ne');\n+    }\n+    query.filter =\n+      options.filter.fieldName + ' ' +\n+      options.filter.operatorString + ' \\'' +\n+      options.filter.literalString + '\\'';\n+  }\n+  if (util.is(options.pageToken, 'string')) {\n+    query.pageToken = options.pageToken;\n+  }\n+\n+  var self = this;\n+  this.makeReq_(\n+    'GET',\n+    '/aggregated/instances',\n+    query,\n+    null, function(err, resp) {\n+      if (err) {\n+        callback(err);\n+        return;\n+      }\n+      if (resp.items) {\n+        var instances = [];\n+        for (var zoneName in resp.items) {\n+          var zone = self.zone(zoneName.replace('zones/', ''));\n+          var zoneInstances = resp.items[zoneName].instances;\n+          if (zoneInstances) {\n+            for (var i = 0; i < zoneInstances.length; i++) {\n+              var metadata = zoneInstances[i];\n+              var instance = zone.instance(metadata.name);\n+              instance.metadata = metadata;\n+              instances.push(instance);\n+            }\n+          }\n+        }\n+        callback(null, instances);\n+      } else {\n+        callback(null, []);\n+      }\n+    });\n+};\n+\n+/**\n+ * Get a list of disks.\n+ *\n+ * @throws {Error} if a malformed filter is provided.\n+ *\n+ * @param {object} options - Disk search options.\n+ * @param {number=} options.maxResults - Maximum number of disks to return.\n+ * @param {object=} options.filter - Search filter.\n+ * @param {string} options.filter.fieldName - Disk field to consider in this\n+ *     filter.\n+ * @param {string} options.filter.operatorString - Filter operator, can be\n+ *     either 'eq' or 'ne'.\n+ * @param {string} options.filter.literalString - String to compare the disk\n+ *     field to. Can be a regular expression.\n+ * @param {string=} pageToken - Page identifier used in paginated search.\n+ * @param {function} callback - The callback function.\n+ *\n+ * @example\n+ * var callback = function(err, disks) {\n+ *   // `disks` is an array of `Disk` objects.\n+ * };\n+ *\n+ * var compute = gcloud.compute({\n+ *   projectId: 'grape-spaceship-123'\n+ * });\n+ *\n+ * compute.getDisks(\n+ *   {\n+ *     filter: {\n+ *       fieldName : 'name',\n+ *       operatorString : 'eq',\n+ *       literalString : 'disk-[0-9]'\n+ *     }],\n+ *   }, callback);\n+ */\n+Compute.prototype.getDisks = function(options, callback) {\n+  if (util.is(options, 'function')) {\n+    callback = options;\n+    options = {};\n+  }\n+\n+  var query = {};\n+\n+  if (util.is(options.maxResults, 'number')) {\n+    query.maxResults = options.maxResults;\n+  }\n+  if (options.filter) {\n+    if (!util.is(options.filter.fieldName, 'string') ||\n+        !util.is(options.filter.operatorString, 'string') ||\n+        !util.is(options.filter.literalString, 'string')) {\n+      throw new Error(\n+        'A filter must have name, comparisonString and literal fields.');\n+    }\n+    if (options.filter.operatorString !== 'eq' &&\n+      options.filter.operatorString !== 'ne') {\n+      throw new Error('Filter operator must be either eq or ne');\n+    }\n+    query.filter =\n+      options.filter.fieldName + ' ' +\n+      options.filter.operatorString + ' \\'' +\n+      options.filter.literalString + '\\'';\n+  }\n+  if (util.is(options.pageToken, 'string')) {\n+    query.pageToken = options.pageToken;\n+  }\n+\n+  var self = this;\n+  this.makeReq_(\n+    'GET',\n+    '/aggregated/disks',\n+    query,\n+    null, function(err, resp) {\n+      if (err) {\n+        callback(err);\n+        return;\n+      }\n+      if (resp.items) {\n+        var disks = [];\n+        for (var zoneName in resp.items) {\n+          var zone = self.zone(zoneName.replace('zones/', ''));\n+          var zoneDisks = resp.items[zoneName].disks;\n+          if (zoneDisks) {\n+            for (var i = 0; i < zoneDisks.length; i++) {\n+              var metadata = zoneDisks[i];\n+              var disk = zone.disk(metadata.name);\n+              disk.metadata = metadata;\n+              disks.push(disk);\n+            }\n+          }\n+        }\n+      } else {\n+        callback(null, []);\n+      }\n+    });\n+};\n+\n+/**\n+ * Get a list of addresses.\n+ *\n+ * @throws {Error} if a malformed filter is provided.\n+ *\n+ * @param {object} options - Address search options.\n+ * @param {number=} options.maxResults - Maximum number of addresses to return.\n+ * @param {object=} options.filter - Search filter.\n+ * @param {string} options.filter.fieldName - Address field to consider in this\n+ *     filter.\n+ * @param {string} options.filter.operatorString - Filter operator, can be\n+ *     either 'eq' or 'ne'.\n+ * @param {string} options.filter.literalString - String to compare the address\n+ *     field to. Can be a regular expression.\n+ * @param {string=} pageToken - Page identifier used in paginated search.\n+ * @param {function} callback - The callback function.\n+ *\n+ * @example\n+ * var callback = function(err, addresses) {\n+ *   // `addresses` is an array of `Address` objects.\n+ * };\n+ *\n+ * var compute = gcloud.compute({\n+ *   projectId: 'grape-spaceship-123'\n+ * });\n+ *\n+ * compute.getAddresses(\n+ *   {\n+ *     filter: {\n+ *       fieldName : 'name',\n+ *       operatorString : 'eq',\n+ *       literalString : 'address-[0-9]'\n+ *     }],\n+ *   }, callback);\n+ */\n+Compute.prototype.getAddresses = function(options, callback) {\n+  if (!callback) {\n+    callback = options;\n+  }\n+\n+  var query = {};\n+\n+  if (options) {\n+    if (util.is(options.maxResults, 'number')) {\n+      query.maxResults = options.maxResults;\n+    }\n+    if (options.filter) {\n+      if (!util.is(options.filter.fieldName, 'string') ||\n+          !util.is(options.filter.operatorString, 'string') ||\n+          !util.is(options.filter.literalString, 'string')) {\n+        throw new Error(\n+          'A filter must have name, comparisonString and literal fields.');\n+      }\n+      if (options.filter.operatorString !== 'eq' &&\n+        options.filter.operatorString !== 'ne') {\n+        throw new Error('Filter operator must be either eq or ne');\n+      }\n+      query.filter =\n+        options.filter.fieldName + ' ' +\n+        options.filter.operatorString + ' \\'' +\n+        options.filter.literalString + '\\'';\n+    }\n+    if (util.is(options.pageToken, 'string')) {\n+      query.pageToken = options.pageToken;\n+    }\n+  }\n+\n+  var self = this;\n+  this.makeReq_(\n+    'GET',\n+    '/aggregated/addresses',\n+    query,\n+    null, function(err, resp) {\n+      if (err) {\n+        callback(err);\n+        return;\n+      }\n+      if (resp.items) {\n+        var addresses = [];\n+        for (var regionName in resp.items) {\n+          var region = self.region(regionName);\n+          var regionAddresses = resp.items[regionName].addresses;\n+          if (regionAddresses) {\n+            for (var i = 0; i < regionAddresses.length; i++) {\n+              var metadata = regionAddresses[i];\n+              var address = region.address(metadata.name);\n+              address.metadata = metadata;\n+              addresses.push(address);\n+            }\n+          }\n+        }\n+        callback(null, addresses);","path":"lib/compute/index.js","position":null,"original_position":569,"commit_id":"68a53f6111abff5bdf104eb3cb4744348e671efe","original_commit_id":"e6070cb81d992f7ef314badffeada6e354c82fb1","user":{"login":"mziccard","id":450933,"avatar_url":"https://avatars.githubusercontent.com/u/450933?v=3","gravatar_id":"","url":"https://api.github.com/users/mziccard","html_url":"https://github.com/mziccard","followers_url":"https://api.github.com/users/mziccard/followers","following_url":"https://api.github.com/users/mziccard/following{/other_user}","gists_url":"https://api.github.com/users/mziccard/gists{/gist_id}","starred_url":"https://api.github.com/users/mziccard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mziccard/subscriptions","organizations_url":"https://api.github.com/users/mziccard/orgs","repos_url":"https://api.github.com/users/mziccard/repos","events_url":"https://api.github.com/users/mziccard/events{/privacy}","received_events_url":"https://api.github.com/users/mziccard/received_events","type":"User","site_admin":false},"body":"Filters are now simple strings, I added auto pagination support and removed filter validation so that we let the API catch those errors. \r\nI added no reference to the API docs yet. Were you thinking about adding a reference on a per-parameter basis or something like: *\"For a detailed description of method options see [API REFERENCE]().\"* on top of the docs that describe a method?","created_at":"2015-07-26T19:18:46Z","updated_at":"2015-07-26T19:18:46Z","html_url":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721#discussion_r35496285","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/comments/35496285"},"html":{"href":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721#discussion_r35496285"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721","id":39856690,"html_url":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721","diff_url":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721.diff","patch_url":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/721","number":721,"state":"open","locked":false,"title":"Add Google Compute Engine support","user":{"login":"mziccard","id":450933,"avatar_url":"https://avatars.githubusercontent.com/u/450933?v=3","gravatar_id":"","url":"https://api.github.com/users/mziccard","html_url":"https://github.com/mziccard","followers_url":"https://api.github.com/users/mziccard/followers","following_url":"https://api.github.com/users/mziccard/following{/other_user}","gists_url":"https://api.github.com/users/mziccard/gists{/gist_id}","starred_url":"https://api.github.com/users/mziccard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mziccard/subscriptions","organizations_url":"https://api.github.com/users/mziccard/orgs","repos_url":"https://api.github.com/users/mziccard/repos","events_url":"https://api.github.com/users/mziccard/events{/privacy}","received_events_url":"https://api.github.com/users/mziccard/received_events","type":"User","site_admin":false},"body":"Fixes #341 \r\nFixes #718 \r\n\r\nThis pull request adds a module to the library to support Google Compute Engine, as described in #718. \r\nThe module is so far capable of:\r\n-  list/create/delete/start/stop/reset instances\r\n-  list/create/delete disks\r\n-  list/create/update firewall rules\r\n-  attach/detach disks to/from instances\r\n\r\nI tried to follow the coding style and added some documentation. The module lacks of tests (both unit and system). I plan to add some unit tests as soon as I have some time to.  \r\n\r\nSuggestions are more than welcome. Feel free to ask for changes/fixes/updates or apply them yourselves, I am happy either way:)","created_at":"2015-07-13T21:08:24Z","updated_at":"2015-07-26T19:18:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f271b15bfd7a0081e0430d33aee6e49b09f01f2a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/721/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/statuses/68a53f6111abff5bdf104eb3cb4744348e671efe","head":{"label":"mziccard:compute-support","ref":"compute-support","sha":"68a53f6111abff5bdf104eb3cb4744348e671efe","user":{"login":"mziccard","id":450933,"avatar_url":"https://avatars.githubusercontent.com/u/450933?v=3","gravatar_id":"","url":"https://api.github.com/users/mziccard","html_url":"https://github.com/mziccard","followers_url":"https://api.github.com/users/mziccard/followers","following_url":"https://api.github.com/users/mziccard/following{/other_user}","gists_url":"https://api.github.com/users/mziccard/gists{/gist_id}","starred_url":"https://api.github.com/users/mziccard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mziccard/subscriptions","organizations_url":"https://api.github.com/users/mziccard/orgs","repos_url":"https://api.github.com/users/mziccard/repos","events_url":"https://api.github.com/users/mziccard/events{/privacy}","received_events_url":"https://api.github.com/users/mziccard/received_events","type":"User","site_admin":false},"repo":{"id":33686483,"name":"gcloud-node","full_name":"mziccard/gcloud-node","owner":{"login":"mziccard","id":450933,"avatar_url":"https://avatars.githubusercontent.com/u/450933?v=3","gravatar_id":"","url":"https://api.github.com/users/mziccard","html_url":"https://github.com/mziccard","followers_url":"https://api.github.com/users/mziccard/followers","following_url":"https://api.github.com/users/mziccard/following{/other_user}","gists_url":"https://api.github.com/users/mziccard/gists{/gist_id}","starred_url":"https://api.github.com/users/mziccard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mziccard/subscriptions","organizations_url":"https://api.github.com/users/mziccard/orgs","repos_url":"https://api.github.com/users/mziccard/repos","events_url":"https://api.github.com/users/mziccard/events{/privacy}","received_events_url":"https://api.github.com/users/mziccard/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mziccard/gcloud-node","description":"Google Cloud Client Library for Node.js","fork":true,"url":"https://api.github.com/repos/mziccard/gcloud-node","forks_url":"https://api.github.com/repos/mziccard/gcloud-node/forks","keys_url":"https://api.github.com/repos/mziccard/gcloud-node/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mziccard/gcloud-node/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mziccard/gcloud-node/teams","hooks_url":"https://api.github.com/repos/mziccard/gcloud-node/hooks","issue_events_url":"https://api.github.com/repos/mziccard/gcloud-node/issues/events{/number}","events_url":"https://api.github.com/repos/mziccard/gcloud-node/events","assignees_url":"https://api.github.com/repos/mziccard/gcloud-node/assignees{/user}","branches_url":"https://api.github.com/repos/mziccard/gcloud-node/branches{/branch}","tags_url":"https://api.github.com/repos/mziccard/gcloud-node/tags","blobs_url":"https://api.github.com/repos/mziccard/gcloud-node/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mziccard/gcloud-node/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mziccard/gcloud-node/git/refs{/sha}","trees_url":"https://api.github.com/repos/mziccard/gcloud-node/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mziccard/gcloud-node/statuses/{sha}","languages_url":"https://api.github.com/repos/mziccard/gcloud-node/languages","stargazers_url":"https://api.github.com/repos/mziccard/gcloud-node/stargazers","contributors_url":"https://api.github.com/repos/mziccard/gcloud-node/contributors","subscribers_url":"https://api.github.com/repos/mziccard/gcloud-node/subscribers","subscription_url":"https://api.github.com/repos/mziccard/gcloud-node/subscription","commits_url":"https://api.github.com/repos/mziccard/gcloud-node/commits{/sha}","git_commits_url":"https://api.github.com/repos/mziccard/gcloud-node/git/commits{/sha}","comments_url":"https://api.github.com/repos/mziccard/gcloud-node/comments{/number}","issue_comment_url":"https://api.github.com/repos/mziccard/gcloud-node/issues/comments{/number}","contents_url":"https://api.github.com/repos/mziccard/gcloud-node/contents/{+path}","compare_url":"https://api.github.com/repos/mziccard/gcloud-node/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mziccard/gcloud-node/merges","archive_url":"https://api.github.com/repos/mziccard/gcloud-node/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mziccard/gcloud-node/downloads","issues_url":"https://api.github.com/repos/mziccard/gcloud-node/issues{/number}","pulls_url":"https://api.github.com/repos/mziccard/gcloud-node/pulls{/number}","milestones_url":"https://api.github.com/repos/mziccard/gcloud-node/milestones{/number}","notifications_url":"https://api.github.com/repos/mziccard/gcloud-node/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mziccard/gcloud-node/labels{/name}","releases_url":"https://api.github.com/repos/mziccard/gcloud-node/releases{/id}","created_at":"2015-04-09T18:50:48Z","updated_at":"2015-05-05T15:47:27Z","pushed_at":"2015-07-26T19:04:45Z","git_url":"git://github.com/mziccard/gcloud-node.git","ssh_url":"git@github.com:mziccard/gcloud-node.git","clone_url":"https://github.com/mziccard/gcloud-node.git","svn_url":"https://github.com/mziccard/gcloud-node","homepage":"https://googlecloudplatform.github.io/gcloud-node","size":10600,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"493ff0cea080f69e397283580de3a4d8555539bd","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":19483273,"name":"gcloud-node","full_name":"GoogleCloudPlatform/gcloud-node","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/gcloud-node","description":"Google Cloud Client Library for Node.js","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/releases{/id}","created_at":"2014-05-06T06:18:00Z","updated_at":"2015-07-26T00:45:46Z","pushed_at":"2015-07-26T19:04:45Z","git_url":"git://github.com/GoogleCloudPlatform/gcloud-node.git","ssh_url":"git@github.com:GoogleCloudPlatform/gcloud-node.git","clone_url":"https://github.com/GoogleCloudPlatform/gcloud-node.git","svn_url":"https://github.com/GoogleCloudPlatform/gcloud-node","homepage":"https://googlecloudplatform.github.io/gcloud-node/","size":14843,"stargazers_count":509,"watchers_count":509,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":88,"mirror_url":null,"open_issues_count":59,"forks":88,"open_issues":59,"watchers":509,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721"},"html":{"href":"https://github.com/GoogleCloudPlatform/gcloud-node/pull/721"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/721"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/721/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/pulls/721/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/statuses/68a53f6111abff5bdf104eb3cb4744348e671efe"}}}}