Skip to content

Commit e964fe8

Browse files
Add Google Cloud DNS
1 parent d4d3d06 commit e964fe8

17 files changed

Lines changed: 2614 additions & 1 deletion

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ To run the system tests, first create and configure a project in the Google Deve
2121

2222
- **GCLOUD_TESTS_PROJECT_ID**: Developers Console project's ID (e.g. bamboo-shift-455)
2323
- **GCLOUD_TESTS_KEY**: The path to the JSON key file.
24+
- ***GCLOUD_TESTS_DNS_DOMAIN*** (*optional*): A domain you own managed by Google Cloud DNS (expected format: `'gcloud-node.com.'`).
2425

2526
Install the [gcloud command-line tool][gcloudcli] to your machine and use it to create the indexes used in the datastore system tests with indexes found in `system-test/data/index/yaml`:
2627

docs/site/components/docs/docs-values.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,25 @@ angular.module('gcloud.docs')
7373
]
7474
},
7575

76+
dns: {
77+
title: 'DNS',
78+
_url: '{baseUrl}/dns',
79+
pages: [
80+
{
81+
title: 'Zone',
82+
url: '/zone'
83+
},
84+
{
85+
title: 'Record',
86+
url: '/record'
87+
},
88+
{
89+
title: 'Change',
90+
url: '/change'
91+
}
92+
]
93+
},
94+
7695
pubsub: {
7796
title: 'PubSub',
7897
_url: '{baseUrl}/pubsub',
@@ -158,6 +177,9 @@ angular.module('gcloud.docs')
158177
'>=0.10.0': ['bigquery'],
159178

160179
// introduce search api.
161-
'>=0.16.0': ['search']
180+
'>=0.16.0': ['search'],
181+
182+
// introduce dns api.
183+
'>=0.17.0': ['dns']
162184
}
163185
});

lib/common/util.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,20 @@ function getType(value) {
256256
return Object.prototype.toString.call(value).match(/\s(\w+)\]/)[1];
257257
}
258258

259+
function exec(name) {
260+
var initialArguments = [].slice.call(arguments, 1);
261+
262+
return function(item) {
263+
if (util.is(item[name], 'function')) {
264+
var invokedArguments = [].slice.call(arguments, 1);
265+
return item[name].apply(item, initialArguments.concat(invokedArguments));
266+
}
267+
return item[name];
268+
};
269+
}
270+
271+
util.exec = exec;
272+
259273
/**
260274
* Used in an Array iterator usually, this will return the value of a property
261275
* in an object by its name.

lib/dns/change.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*!
2+
* Copyright 2014 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*!
18+
* @module dns/change
19+
*/
20+
21+
'use strict';
22+
23+
/**
24+
* @constructor
25+
* @alias module:dns/change
26+
*
27+
* @param {module:dns/zone} zone - The parent zone object.
28+
* @param {string} id - ID of the change.
29+
*/
30+
function Change(zone, id) {
31+
this.zoneName = zone.name;
32+
this.id = id;
33+
34+
this.metadata = {};
35+
this.makeReq_ = zone.dns.makeReq_.bind(zone.dns);
36+
}
37+
38+
/**
39+
* Get the metadata for the change in the zone.
40+
*
41+
* @param {function} callback - The callback function.
42+
* @param {?error} callback.err - An API error.
43+
* @param {?object} callback.metadata - Metadata of the change from the API.
44+
* @param {object} callback.apiResponse - Raw API response.
45+
*/
46+
Change.prototype.getMetadata = function(callback) {
47+
var self = this;
48+
var path = '/managedZones/' + this.zoneName + '/changes/' + this.id;
49+
50+
this.makeReq_('GET', path, null, null, function(err, resp) {
51+
if (err) {
52+
callback(err, null, resp);
53+
return;
54+
}
55+
56+
self.metadata = resp;
57+
58+
callback(null, self.metadata, resp);
59+
});
60+
};
61+
62+
module.exports = Change;

lib/dns/index.js

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*!
2+
* Copyright 2014 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*!
18+
* @module dns
19+
*/
20+
21+
'use strict';
22+
23+
var extend = require('extend');
24+
25+
/**
26+
* @type {module:common/streamrouter}
27+
* @private
28+
*/
29+
var streamRouter = require('../common/stream-router.js');
30+
31+
/**
32+
* @type {module:common/util}
33+
* @private
34+
*/
35+
var util = require('../common/util.js');
36+
37+
/**
38+
* @type {module:dns/zone}
39+
* @private
40+
*/
41+
var Zone = require('./zone.js');
42+
43+
/**
44+
* @const {string} Base URL for DNS API.
45+
* @private
46+
*/
47+
var DNS_BASE_URL = 'https://www.googleapis.com/dns/v1/projects/';
48+
49+
/**
50+
* @const {array} Required scopes for the DNS API.
51+
* @private
52+
*/
53+
var SCOPES = [
54+
'https://www.googleapis.com/auth/ndev.clouddns.readwrite',
55+
'https://www.googleapis.com/auth/cloud-platform'
56+
];
57+
58+
/**
59+
* [Google Cloud DNS](https://cloud.google.com/dns) is a reliable, resilient,
60+
* low-latency DNS serving from Google’s worldwide network of Anycast DNS
61+
* servers.
62+
*
63+
* @constructor
64+
* @alias module:dns
65+
*
66+
* @param {object} options - [Configuration object](#/docs/?method=gcloud).
67+
*
68+
* @example
69+
* var gcloud = require('gcloud')({
70+
* keyFilename: '/path/to/keyfile.json',
71+
* projectId: 'grape-spaceship-123'
72+
* });
73+
*
74+
* var dns = gcloud.dns();
75+
*/
76+
function DNS(options) {
77+
if (!(this instanceof DNS)) {
78+
return new DNS(options);
79+
}
80+
81+
options = options || {};
82+
83+
if (!options.projectId) {
84+
throw util.missingProjectIdError;
85+
}
86+
87+
this.makeAuthorizedRequest_ = util.makeAuthorizedRequestFactory({
88+
credentials: options.credentials,
89+
keyFile: options.keyFilename,
90+
scopes: SCOPES,
91+
email: options.email
92+
});
93+
94+
this.projectId_ = options.projectId;
95+
}
96+
97+
/**
98+
* Create a managed zone.
99+
*
100+
* @throws {error} If a zone name is not provided.
101+
* @throws {error} If a zone dnsName is not provided.
102+
*
103+
* @param {string} name - Unique name for the zone. E.g. "my-zone"
104+
* @param {object} config - Configuration object.
105+
* @param {string} config.dnsName - DNS name for the zone. E.g. "example.com."
106+
* @param {string=} config.description - Description text for the zone.
107+
* @param {function} callback - The callback function.
108+
* @param {?error} callback.err - An API error.
109+
* @param {?module:dns/zone} callback.zone - A new {module:dns/zone} object.
110+
* @param {object} callback.apiResponse - Raw API response.
111+
*
112+
* @example
113+
* dns.createZone('my-awesome-zone', {
114+
* dnsName: 'example.com.', // note the period at the end of the domain.
115+
* description: 'This zone is awesome!'
116+
* }, function(err, zone, apiResponse) {
117+
* if (!err) {
118+
* // The zone was created successfully.
119+
* }
120+
* });
121+
*/
122+
DNS.prototype.createZone = function(name, config, callback) {
123+
var self = this;
124+
125+
if (!name) {
126+
throw new Error('A zone name is required.');
127+
}
128+
129+
if (!config || !config.dnsName) {
130+
throw new Error('A zone dnsName is required.');
131+
}
132+
133+
config.name = name;
134+
135+
// Required by the API.
136+
config.description = config.description || '';
137+
138+
this.makeReq_('POST', '/managedZones', null, config, function(err, resp) {
139+
if (err) {
140+
callback(err, null, resp);
141+
return;
142+
}
143+
144+
var zone = self.zone(resp.name);
145+
zone.metadata = resp;
146+
147+
callback(null, zone, resp);
148+
});
149+
};
150+
151+
/**
152+
* Gets a list of managed zones for the project.
153+
*
154+
* @param {object=} query - Query object.
155+
* @param {number} query.maxResults - Maximum number of results to return.
156+
* @param {string} query.pageToken - Page token.
157+
* @param {function} callback - The callback function.
158+
* @param {?error} callback.err - An API error.
159+
* @param {?module:dns/zone[]} callback.zones - An array of {module:dns/zone}
160+
* objects.
161+
* @param {object} callback.apiResponse - Raw API response.
162+
*
163+
* @example
164+
* dns.getZones(function(err, zones, apiResponse) {});
165+
*/
166+
DNS.prototype.getZones = function(query, callback) {
167+
var self = this;
168+
169+
if (util.is(query, 'function')) {
170+
callback = query;
171+
query = {};
172+
}
173+
174+
this.makeReq_('GET', '/managedZones', query, null, function(err, resp) {
175+
if (err) {
176+
callback(err, null, null, resp);
177+
return;
178+
}
179+
180+
var zones = (resp.managedZones || []).map(function(zone) {
181+
var zoneInstance = self.zone(zone.name);
182+
zoneInstance.metadata = zone;
183+
return zoneInstance;
184+
});
185+
186+
var nextQuery = null;
187+
188+
if (resp.nextPageToken) {
189+
nextQuery = extend({}, query, {
190+
pageToken: resp.nextPageToken
191+
});
192+
}
193+
194+
callback(null, zones, nextQuery, resp);
195+
});
196+
};
197+
198+
/**
199+
* Create a zone object representing an existing managed zone.
200+
*
201+
* @throws {error} If a zone name is not provided.
202+
*
203+
* @param {string} name - The unique name of the zone.
204+
* @return {module:dns/zone}
205+
*
206+
* @example
207+
* var zone = dns.zone('my-zone');
208+
*/
209+
DNS.prototype.zone = function(name) {
210+
if (!name) {
211+
throw new Error('A zone name is required.');
212+
}
213+
214+
return new Zone(this, name);
215+
};
216+
217+
/**
218+
* Make a new request object from the provided arguments and wrap the callback
219+
* to intercept non-successful responses.
220+
*
221+
* @private
222+
*
223+
* @param {string} method - Action.
224+
* @param {string} path - Request path.
225+
* @param {*} query - Request query object.
226+
* @param {*} body - Request body contents.
227+
* @param {function} callback - The callback function.
228+
*/
229+
DNS.prototype.makeReq_ = function(method, path, query, body, callback) {
230+
var reqOpts = {
231+
method: method,
232+
qs: query,
233+
uri: DNS_BASE_URL + this.projectId_ + path
234+
};
235+
236+
if (body) {
237+
reqOpts.json = body;
238+
}
239+
240+
this.makeAuthorizedRequest_(reqOpts, callback);
241+
};
242+
243+
/*! Developer Documentation
244+
*
245+
* These methods can be used with either a callback or as a readable object
246+
* stream. `streamRouter` is used to add this dual behavior.
247+
*/
248+
streamRouter.extend(DNS, 'getZones');
249+
250+
module.exports = DNS;

0 commit comments

Comments
 (0)