Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.

Properly group records from a zonefile. #26

Merged
merged 3 commits into from
Mar 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@
"dns-zonefile": "0.2.2",
"extend": "^3.0.0",
"is": "^3.0.1",
"lodash.flatten": "^4.4.0",
"lodash.groupby": "^4.6.0",
"methmeth": "^1.0.0",
"propprop": "^0.3.1",
"string-format-obj": "^1.0.0"
},
"devDependencies": {
Expand Down
39 changes: 34 additions & 5 deletions src/zone.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ var arrify = require('arrify');
var common = require('@google-cloud/common');
var exec = require('methmeth');
var extend = require('extend');
var flatten = require('lodash.flatten');
var fs = require('fs');
var groupBy = require('lodash.groupby');
var is = require('is');
var prop = require('propprop');
var util = require('util');
var zonefile = require('dns-zonefile');

Expand Down Expand Up @@ -342,14 +345,40 @@ Zone.prototype.createChange = function(config, callback) {
throw new Error('Cannot create a change with no additions or deletions.');
}

var body = extend({}, config, {
additions: arrify(config.add).map(exec('toJSON')),
deletions: arrify(config.delete).map(exec('toJSON')),
});

var body = extend(
{
additions: groupByType(arrify(config.add).map(exec('toJSON'))),
deletions: groupByType(arrify(config.delete).map(exec('toJSON'))),
},
config
);
delete body.add;
delete body.delete;

function groupByType(changes) {
changes = groupBy(changes, 'type');

var changesArray = [];

for (var recordType in changes) {
var recordsByName = groupBy(changes[recordType], 'name');

for (var recordName in recordsByName) {
var records = recordsByName[recordName];
var templateRecord = extend({}, records[0]);

if (records.length > 1) {
// Combine the `rrdatas` values from all records of the same type.
templateRecord.rrdatas = flatten(records.map(prop('rrdatas')));
}

changesArray.push(templateRecord);
}
}

return changesArray;
}

this.request(
{
method: 'POST',
Expand Down
6 changes: 6 additions & 0 deletions system-test/data/zonefile.zone
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
$TTL 3600
{DNS_DOMAIN} 21600 IN SPF "v=spf1" "mx:{DNS_DOMAIN}" "-all"
{DNS_DOMAIN} IN TXT "google-site-verification=xxxxxxxxxxxxYYYYYYXXX"
{DNS_DOMAIN} 21600 MX 10 mail.example.com.
{DNS_DOMAIN} 21600 MX 30 mail.example.com.
{DNS_DOMAIN} A 128.9.0.32
A 10.1.0.52
{DNS_DOMAIN} A 10.2.0.27
A 128.9.0.33
78 changes: 52 additions & 26 deletions test/zone.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@

var arrify = require('arrify');
var assert = require('assert');
var exec = require('methmeth');
var extend = require('extend');
var flatten = require('lodash.flatten');
var nodeutil = require('util');
var prop = require('propprop');
var proxyquire = require('proxyquire');
var ServiceObject = require('@google-cloud/common').ServiceObject;
var util = require('@google-cloud/common').util;
var uuid = require('uuid');

var promisified = false;
var fakeUtil = extend({}, util, {
Expand Down Expand Up @@ -192,26 +196,33 @@ describe('Zone', function() {
});

describe('createChange', function() {
function generateRecord(recordJson) {
recordJson = extend(
{
name: uuid.v1(),
type: uuid.v1(),
rrdatas: [uuid.v1(), uuid.v1()],
},
recordJson
);

return {
toJSON: function() {
return recordJson;
},
};
}

it('should throw error if add or delete is not provided', function() {
assert.throws(function() {
zone.createChange({}, util.noop);
}, /Cannot create a change with no additions or deletions/);
});

it('should parse and rename add to additions', function(done) {
var recordsToAdd = [
{
toJSON: function() {
return 'a';
},
},
{
toJSON: function() {
return 'a';
},
},
];
var expectedAdditions = ['a', 'a'];
var recordsToAdd = [generateRecord(), generateRecord()];

var expectedAdditions = recordsToAdd.map(exec('toJSON'));

zone.request = function(reqOpts) {
assert.strictEqual(reqOpts.json.add, undefined);
Expand All @@ -223,19 +234,9 @@ describe('Zone', function() {
});

it('should parse and rename delete to deletions', function(done) {
var recordsToDelete = [
{
toJSON: function() {
return 'a';
},
},
{
toJSON: function() {
return 'a';
},
},
];
var expectedDeletions = ['a', 'a'];
var recordsToDelete = [generateRecord(), generateRecord()];

var expectedDeletions = recordsToDelete.map(exec('toJSON'));

zone.request = function(reqOpts) {
assert.strictEqual(reqOpts.json.delete, undefined);
Expand All @@ -246,6 +247,31 @@ describe('Zone', function() {
zone.createChange({delete: recordsToDelete}, assert.ifError);
});

it('should group changes by name and type', function(done) {
var recordsToAdd = [
generateRecord({name: 'name.com.', type: 'mx'}),
generateRecord({name: 'name.com.', type: 'mx'}),
];

zone.request = function(reqOpts) {
var expectedRRDatas = flatten(
recordsToAdd.map(exec('toJSON')).map(prop('rrdatas'))
);

assert.deepStrictEqual(reqOpts.json.additions, [
{
name: 'name.com.',
type: 'mx',
rrdatas: expectedRRDatas,
},
]);

done();
};

zone.createChange({add: recordsToAdd}, assert.ifError);
});

it('should make correct API request', function(done) {
zone.request = function(reqOpts) {
assert.strictEqual(reqOpts.method, 'POST');
Expand Down