Files
cloudron-box/src/test/dns-test.js

653 lines
23 KiB
JavaScript
Raw Normal View History

2016-11-30 15:35:58 +01:00
/* jslint node:true */
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict';
var async = require('async'),
2016-11-30 18:04:47 +01:00
AWS = require('aws-sdk'),
2017-09-05 22:23:24 +02:00
GCDNS = require('@google-cloud/dns'),
2017-01-10 16:44:28 -08:00
config = require('../config.js'),
2016-11-30 15:35:58 +01:00
database = require('../database.js'),
expect = require('expect.js'),
nock = require('nock'),
settings = require('../settings.js'),
2017-10-29 01:16:36 +02:00
domains = require('../domains.js'),
2016-11-30 18:04:47 +01:00
util = require('util');
2016-11-30 15:35:58 +01:00
describe('dns provider', function () {
before(function (done) {
config._reset();
2016-11-30 15:35:58 +01:00
async.series([
database.initialize,
settings.initialize
2016-11-30 15:35:58 +01:00
], done);
});
after(function (done) {
database._clear(done);
});
describe('noop', function () {
before(function (done) {
var data = {
provider: 'noop'
};
config.setFqdn('example.com');
config.setZoneName('example.com');
settings.setDnsConfig(data, config.fqdn(), config.zoneName(), done);
2016-11-30 15:35:58 +01:00
});
it('upsert succeeds', function (done) {
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
2016-11-30 15:35:58 +01:00
expect(error).to.eql(null);
expect(result).to.eql('noop-record-id');
done();
});
});
it('get succeeds', function (done) {
2017-10-29 01:16:36 +02:00
domains.getDNSRecords('test.example.com', 'A', function (error, result) {
2016-11-30 15:35:58 +01:00
expect(error).to.eql(null);
expect(result).to.be.an(Array);
expect(result.length).to.eql(0);
done();
});
});
it('del succeeds', function (done) {
2017-10-29 01:16:36 +02:00
domains.removeDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error) {
2016-11-30 15:35:58 +01:00
expect(error).to.eql(null);
done();
});
});
});
describe('digitalocean', function () {
var TOKEN = 'sometoken';
var DIGITALOCEAN_ENDPOINT = 'https://api.digitalocean.com';
before(function (done) {
var data = {
provider: 'digitalocean',
token: TOKEN
};
config.setFqdn('example.com');
config.setZoneName('example.com');
settings.setDnsConfig(data, config.fqdn(), config.zoneName(), done);
});
it('upsert non-existing record succeeds', function (done) {
nock.cleanAll();
var DOMAIN_RECORD_0 = {
id: 3352892,
type: 'A',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var req1 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.get('/v2/domains/' + config.zoneName() + '/records')
.reply(200, { domain_records: [] });
var req2 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.post('/v2/domains/' + config.zoneName() + '/records')
.reply(201, { domain_record: DOMAIN_RECORD_0 });
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
expect(error).to.eql(null);
expect(result).to.eql('3352892');
expect(req1.isDone()).to.be.ok();
expect(req2.isDone()).to.be.ok();
done();
});
});
it('upsert existing record succeeds', function (done) {
nock.cleanAll();
var DOMAIN_RECORD_0 = {
id: 3352892,
type: 'A',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1 = {
id: 3352893,
type: 'A',
name: 'test',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1_NEW = {
id: 3352893,
type: 'A',
name: 'test',
data: '1.2.3.5',
priority: null,
port: null,
weight: null
};
var req1 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.get('/v2/domains/' + config.zoneName() + '/records')
.reply(200, { domain_records: [ DOMAIN_RECORD_0, DOMAIN_RECORD_1 ] });
var req2 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.put('/v2/domains/' + config.zoneName() + '/records/' + DOMAIN_RECORD_1.id)
.reply(200, { domain_record: DOMAIN_RECORD_1_NEW });
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ DOMAIN_RECORD_1_NEW.data ], function (error, result) {
expect(error).to.eql(null);
expect(result).to.eql('3352893');
expect(req1.isDone()).to.be.ok();
expect(req2.isDone()).to.be.ok();
done();
});
});
it('upsert multiple record succeeds', function (done) {
nock.cleanAll();
var DOMAIN_RECORD_0 = {
id: 3352892,
type: 'A',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1 = {
id: 3352893,
type: 'TXT',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1_NEW = {
id: 3352893,
type: 'TXT',
name: '@',
data: 'somethingnew',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_2 = {
id: 3352894,
type: 'TXT',
name: '@',
data: 'something',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_2_NEW = {
id: 3352894,
type: 'TXT',
name: '@',
data: 'somethingnew',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_3_NEW = {
id: 3352895,
type: 'TXT',
name: '@',
data: 'thirdnewone',
priority: null,
port: null,
weight: null
};
var req1 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.get('/v2/domains/' + config.zoneName() + '/records')
.reply(200, { domain_records: [ DOMAIN_RECORD_0, DOMAIN_RECORD_1, DOMAIN_RECORD_2 ] });
var req2 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.put('/v2/domains/' + config.zoneName() + '/records/' + DOMAIN_RECORD_1.id)
.reply(200, { domain_record: DOMAIN_RECORD_1_NEW });
var req3 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.put('/v2/domains/' + config.zoneName() + '/records/' + DOMAIN_RECORD_2.id)
.reply(200, { domain_record: DOMAIN_RECORD_2_NEW });
var req4 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.post('/v2/domains/' + config.zoneName() + '/records')
.reply(201, { domain_record: DOMAIN_RECORD_2_NEW });
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords(config.fqdn(), 'TXT', [ DOMAIN_RECORD_2_NEW.data, DOMAIN_RECORD_1_NEW.data, DOMAIN_RECORD_3_NEW.data ], function (error, result) {
expect(error).to.eql(null);
expect(result).to.eql('3352893');
expect(req1.isDone()).to.be.ok();
expect(req2.isDone()).to.be.ok();
expect(req3.isDone()).to.be.ok();
expect(req4.isDone()).to.be.ok();
done();
});
});
it('get succeeds', function (done) {
nock.cleanAll();
var DOMAIN_RECORD_0 = {
id: 3352892,
type: 'A',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1 = {
id: 3352893,
type: 'A',
name: 'test',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var req1 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.get('/v2/domains/' + config.zoneName() + '/records')
.reply(200, { domain_records: [ DOMAIN_RECORD_0, DOMAIN_RECORD_1 ] });
2017-10-29 01:16:36 +02:00
domains.getDNSRecords('test.example.com', 'A', function (error, result) {
expect(error).to.eql(null);
expect(result).to.be.an(Array);
expect(result.length).to.eql(1);
expect(result[0]).to.eql(DOMAIN_RECORD_1.data);
expect(req1.isDone()).to.be.ok();
done();
});
});
it('del succeeds', function (done) {
nock.cleanAll();
var DOMAIN_RECORD_0 = {
id: 3352892,
type: 'A',
name: '@',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var DOMAIN_RECORD_1 = {
id: 3352893,
type: 'A',
name: 'test',
data: '1.2.3.4',
priority: null,
port: null,
weight: null
};
var req1 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.get('/v2/domains/' + config.zoneName() + '/records')
.reply(200, { domain_records: [ DOMAIN_RECORD_0, DOMAIN_RECORD_1 ] });
var req2 = nock(DIGITALOCEAN_ENDPOINT).filteringRequestBody(function () { return false; })
.delete('/v2/domains/' + config.zoneName() + '/records/' + DOMAIN_RECORD_1.id)
.reply(204, {});
2017-10-29 01:16:36 +02:00
domains.removeDNSRecords('test.example.com', 'A', ['1.2.3.4'], function (error) {
expect(error).to.eql(null);
expect(req1.isDone()).to.be.ok();
expect(req2.isDone()).to.be.ok();
done();
});
});
});
2016-11-30 18:04:47 +01:00
describe('route53', function () {
config.setFqdn('example.com');
config.setZoneName('example.com');
2016-11-30 18:04:47 +01:00
// do not clear this with [] but .length = 0 so we don't loose the reference in mockery
var awsAnswerQueue = [];
var AWS_HOSTED_ZONES = {
HostedZones: [{
Id: '/hostedzone/Z34G16B38TNZ9L',
Name: config.zoneName() + '.',
2016-11-30 18:04:47 +01:00
CallerReference: '305AFD59-9D73-4502-B020-F4E6F889CB30',
ResourceRecordSetCount: 2,
ChangeInfo: {
Id: '/change/CKRTFJA0ANHXB',
Status: 'INSYNC'
}
}, {
Id: '/hostedzone/Z3OFC3B6E8YTA7',
Name: 'cloudron.us.',
CallerReference: '0B37F2DE-21A4-E678-BA32-3FC8AF0CF635',
Config: {},
ResourceRecordSetCount: 2,
ChangeInfo: {
Id: '/change/C2682N5HXP0BZ5',
Status: 'INSYNC'
}
}],
IsTruncated: false,
MaxItems: '100'
};
before(function (done) {
var data = {
provider: 'route53',
accessKeyId: 'unused',
secretAccessKey: 'unused'
};
function mockery (queue) {
return function(options, callback) {
expect(options).to.be.an(Object);
var elem = queue.shift();
if (!util.isArray(elem)) throw(new Error('Mock answer required'));
// if no callback passed, return a req object with send();
if (typeof callback !== 'function') {
return {
httpRequest: { headers: {} },
send: function (callback) {
expect(callback).to.be.a(Function);
callback(elem[0], elem[1]);
}
};
} else {
callback(elem[0], elem[1]);
}
};
}
function Route53Mock(cfg) {
expect(cfg).to.eql({
accessKeyId: data.accessKeyId,
secretAccessKey: data.secretAccessKey,
region: 'us-east-1'
});
}
Route53Mock.prototype.getHostedZone = mockery(awsAnswerQueue);
Route53Mock.prototype.getChange = mockery(awsAnswerQueue);
Route53Mock.prototype.changeResourceRecordSets = mockery(awsAnswerQueue);
Route53Mock.prototype.listResourceRecordSets = mockery(awsAnswerQueue);
Route53Mock.prototype.listHostedZones = mockery(awsAnswerQueue);
// override route53 in AWS
// Comment this out and replace the config with real tokens to test against AWS proper
2017-02-07 01:27:56 -08:00
AWS._originalRoute53 = AWS.Route53;
2016-11-30 18:04:47 +01:00
AWS.Route53 = Route53Mock;
settings.setDnsConfig(data, config.fqdn(), config.zoneName(), done);
2016-11-30 18:04:47 +01:00
});
2017-02-07 01:27:56 -08:00
after(function () {
AWS.Route53 = AWS._originalRoute53;
delete AWS._originalRoute53;
});
2016-11-30 18:04:47 +01:00
it('upsert non-existing record succeeds', function (done) {
awsAnswerQueue.push([null, AWS_HOSTED_ZONES]);
awsAnswerQueue.push([null, {
ChangeInfo: {
Id: '/change/C2QLKQIWEI0BZF',
Status: 'PENDING',
SubmittedAt: 'Mon Aug 04 2014 17: 44: 49 GMT - 0700(PDT)'
}
}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
2016-11-30 18:04:47 +01:00
expect(error).to.eql(null);
expect(result).to.eql('/change/C2QLKQIWEI0BZF');
expect(awsAnswerQueue.length).to.eql(0);
done();
});
});
it('upsert existing record succeeds', function (done) {
awsAnswerQueue.push([null, AWS_HOSTED_ZONES]);
awsAnswerQueue.push([null, {
ChangeInfo: {
Id: '/change/C2QLKQIWEI0BZF',
Status: 'PENDING',
SubmittedAt: 'Mon Aug 04 2014 17: 44: 49 GMT - 0700(PDT)'
}
}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
2016-11-30 18:04:47 +01:00
expect(error).to.eql(null);
expect(result).to.eql('/change/C2QLKQIWEI0BZF');
expect(awsAnswerQueue.length).to.eql(0);
done();
});
});
it('upsert multiple record succeeds', function (done) {
awsAnswerQueue.push([null, AWS_HOSTED_ZONES]);
awsAnswerQueue.push([null, {
ChangeInfo: {
Id: '/change/C2QLKQIWEI0BZF',
Status: 'PENDING',
SubmittedAt: 'Mon Aug 04 2014 17: 44: 49 GMT - 0700(PDT)'
}
}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords(config.fqdn(), 'TXT', [ 'first', 'second', 'third' ], function (error, result) {
2016-11-30 18:04:47 +01:00
expect(error).to.eql(null);
expect(result).to.eql('/change/C2QLKQIWEI0BZF');
expect(awsAnswerQueue.length).to.eql(0);
done();
});
});
it('get succeeds', function (done) {
awsAnswerQueue.push([null, AWS_HOSTED_ZONES]);
awsAnswerQueue.push([null, {
ResourceRecordSets: [{
Name: 'test.' + config.zoneName() + '.',
2016-11-30 18:04:47 +01:00
Type: 'A',
ResourceRecords: [{
Value: '1.2.3.4'
}]
}]
}]);
2017-10-29 01:16:36 +02:00
domains.getDNSRecords('test.example.com', 'A', function (error, result) {
2016-11-30 18:04:47 +01:00
expect(error).to.eql(null);
expect(result).to.be.an(Array);
expect(result.length).to.eql(1);
expect(result[0]).to.eql('1.2.3.4');
expect(awsAnswerQueue.length).to.eql(0);
done();
});
});
it('del succeeds', function (done) {
awsAnswerQueue.push([null, AWS_HOSTED_ZONES]);
awsAnswerQueue.push([null, {
ChangeInfo: {
Id: '/change/C2QLKQIWEI0BZF',
Status: 'PENDING',
SubmittedAt: 'Mon Aug 04 2014 17: 44: 49 GMT - 0700(PDT)'
}
}]);
2017-10-29 01:16:36 +02:00
domains.removeDNSRecords('test.example.com', 'A', ['1.2.3.4'], function (error) {
2016-11-30 18:04:47 +01:00
expect(error).to.eql(null);
expect(awsAnswerQueue.length).to.eql(0);
done();
});
});
});
2017-09-05 22:23:24 +02:00
describe('gcdns', function () {
var HOSTED_ZONES = [];
var zoneQueue = [];
var _OriginalGCDNS;
before(function (done) {
var domain = 'example.com';
config.setFqdn(domain);
config.setZoneName(domain);
var dnsConfig = {
provider: 'gcdns',
projectId: 'my-dns-proj',
keyFilename: __dirname + '/syn-im-1ec6f9f870bf.json'
2017-09-05 22:23:24 +02:00
};
function mockery (queue) {
return function() {
var callback = arguments[--arguments.length];
var elem = queue.shift();
if (!util.isArray(elem)) throw(new Error('Mock answer required'));
// if no callback passed, return a req object with send();
if (typeof callback !== 'function') {
return {
httpRequest: { headers: {} },
send: function (callback) {
expect(callback).to.be.a(Function);
callback.apply(callback, elem);
}
};
} else {
callback.apply(callback, elem);
}
};
}
function fakeZone(name, ns, recordQueue) {
var zone = GCDNS().zone(name.replace('.', '-'));
zone.metadata.dnsName = name + '.';
zone.metadata.nameServers = ns || ['8.8.8.8', '8.8.4.4'];
zone.getRecords = mockery(recordQueue || zoneQueue);
zone.createChange = mockery(recordQueue || zoneQueue);
2017-09-05 22:23:24 +02:00
zone.replaceRecords = mockery(recordQueue || zoneQueue);
zone.deleteRecords = mockery(recordQueue || zoneQueue);
return zone;
}
HOSTED_ZONES = [fakeZone(domain), fakeZone('cloudron.us')];
_OriginalGCDNS = GCDNS.prototype.getZones;
GCDNS.prototype.getZones = mockery(zoneQueue);
settings.setDnsConfig(dnsConfig, config.fqdn(), config.zoneName(), done);
});
after(function () {
GCDNS.prototype.getZones = _OriginalGCDNS;
_OriginalGCDNS = null;
});
it('upsert non-existing record succeeds', function (done) {
zoneQueue.push([null, HOSTED_ZONES]); // getZone
zoneQueue.push([null, [ ]]); // getRecords
2017-09-05 22:23:24 +02:00
zoneQueue.push([null, {id: '1'}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
2017-09-05 22:23:24 +02:00
expect(error).to.eql(null);
expect(result).to.eql('1');
expect(zoneQueue.length).to.eql(0);
done();
});
});
it('upsert existing record succeeds', function (done) {
zoneQueue.push([null, HOSTED_ZONES]);
zoneQueue.push([null, [GCDNS().zone('test').record('A', {'name': 'test', data:['5.6.7.8'], ttl: 1})]]);
2017-09-05 22:23:24 +02:00
zoneQueue.push([null, {id: '2'}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords('test.example.com', 'A', [ '1.2.3.4' ], function (error, result) {
2017-09-05 22:23:24 +02:00
expect(error).to.eql(null);
expect(result).to.eql('2');
expect(zoneQueue.length).to.eql(0);
done();
});
});
it('upsert multiple record succeeds', function (done) {
zoneQueue.push([null, HOSTED_ZONES]);
zoneQueue.push([null, [ ]]); // getRecords
2017-09-05 22:23:24 +02:00
zoneQueue.push([null, {id: '3'}]);
2017-10-29 01:16:36 +02:00
domains.upsertDNSRecords(config.fqdn(), 'TXT', [ 'first', 'second', 'third' ], function (error, result) {
2017-09-05 22:23:24 +02:00
expect(error).to.eql(null);
expect(result).to.eql('3');
expect(zoneQueue.length).to.eql(0);
done();
});
});
it('get succeeds', function (done) {
zoneQueue.push([null, HOSTED_ZONES]);
zoneQueue.push([null, [GCDNS().zone('test').record('A', {'name': 'test', data:['1.2.3.4', '5.6.7.8'], ttl: 1})]]);
2017-09-05 22:23:24 +02:00
2017-10-29 01:16:36 +02:00
domains.getDNSRecords('test.example.com', 'A', function (error, result) {
2017-09-05 22:23:24 +02:00
expect(error).to.eql(null);
expect(result).to.be.an(Array);
expect(result.length).to.eql(2);
expect(result).to.eql(['1.2.3.4', '5.6.7.8']);
2017-09-05 22:23:24 +02:00
expect(zoneQueue.length).to.eql(0);
done();
});
});
it('del succeeds', function (done) {
zoneQueue.push([null, HOSTED_ZONES]);
zoneQueue.push([null, [GCDNS().zone('test').record('A', {'name': 'test', data:['5.6.7.8'], ttl: 1})]]);
2017-09-05 22:23:24 +02:00
zoneQueue.push([null, {id: '5'}]);
2017-10-29 01:16:36 +02:00
domains.removeDNSRecords('test.example.com', 'A', ['1.2.3.4'], function (error) {
2017-09-05 22:23:24 +02:00
expect(error).to.eql(null);
expect(zoneQueue.length).to.eql(0);
done();
});
});
});
2016-11-30 15:35:58 +01:00
});