implemented cleanup/update of DNS records on config change
This commit is contained in:
parent
acf2fd7764
commit
82f0b45c56
|
@ -23,7 +23,7 @@ module.exports.create = function (deps, conf) {
|
||||||
var tldObj = {};
|
var tldObj = {};
|
||||||
resp.data.forEach(function (tldInfo) {
|
resp.data.forEach(function (tldInfo) {
|
||||||
if (tldInfo.enabled) {
|
if (tldInfo.enabled) {
|
||||||
tldObj[tldInfo.com] = true;
|
tldObj[tldInfo.tld] = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ module.exports.create = function (deps, conf) {
|
||||||
// rare even if the assumption isn't valid.
|
// rare even if the assumption isn't valid.
|
||||||
return {
|
return {
|
||||||
tld: split.slice(-tldSegCnt).join('.')
|
tld: split.slice(-tldSegCnt).join('.')
|
||||||
, sld: split.slice(-tldSegCnt-1, 1)
|
, sld: split.slice(-tldSegCnt-1, -tldSegCnt).join('.')
|
||||||
, sub: split.slice(0, -tldSegCnt-1)
|
, sub: split.slice(0, -tldSegCnt-1).join('.')
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -152,8 +152,23 @@ module.exports.create = function (deps, conf) {
|
||||||
return (dev || {}).addresses || [];
|
return (dev || {}).addresses || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function removeDomains(session, domains) {
|
||||||
|
var directives = await deps.OAUTH3.discover(session.token.aud);
|
||||||
|
|
||||||
|
var oldDns = await splitDomains(directives.api, domains);
|
||||||
|
var common = {
|
||||||
|
api: 'devices.detach'
|
||||||
|
, session: session
|
||||||
|
, device: conf.device.hostname
|
||||||
|
};
|
||||||
|
await deps.PromiseA.all(oldDns.map(function (record) {
|
||||||
|
return deps.OAUTH3.api(directives.api, Object.assign({}, common, record));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDeviceAddresses: getDeviceAddresses
|
getDeviceAddresses
|
||||||
, setDeviceAddress: setDeviceAddress
|
, setDeviceAddress
|
||||||
|
, removeDomains
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,12 +8,13 @@ module.exports.create = function (deps, conf) {
|
||||||
|
|
||||||
var loopbackDomain;
|
var loopbackDomain;
|
||||||
|
|
||||||
function iterateAllModules(action) {
|
function iterateAllModules(action, curConf) {
|
||||||
var promises = conf.ddns.modules.map(function (mod) {
|
curConf = curConf || conf;
|
||||||
|
var promises = curConf.ddns.modules.map(function (mod) {
|
||||||
return action(mod, mod.domains);
|
return action(mod, mod.domains);
|
||||||
});
|
});
|
||||||
|
|
||||||
conf.domains.forEach(function (dom) {
|
curConf.domains.forEach(function (dom) {
|
||||||
if (!dom.modules || !Array.isArray(dom.modules.ddns) || !dom.modules.ddns.length) {
|
if (!dom.modules || !Array.isArray(dom.modules.ddns) || !dom.modules.ddns.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -168,6 +169,87 @@ module.exports.create = function (deps, conf) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getModuleDiffs(prevConf) {
|
||||||
|
var prevMods = {};
|
||||||
|
var curMods = {};
|
||||||
|
|
||||||
|
// this returns a Promise, but since the functions we use are synchronous
|
||||||
|
// and change our enclosed variables we don't need to wait for the return.
|
||||||
|
iterateAllModules(function (mod, domainList) {
|
||||||
|
if (mod.type !== 'dns@oauth3.org') { return; }
|
||||||
|
|
||||||
|
prevMods[mod.id] = { mod, domainList };
|
||||||
|
return true;
|
||||||
|
}, prevConf);
|
||||||
|
iterateAllModules(function (mod, domainList) {
|
||||||
|
if (mod.type !== 'dns@oauth3.org') { return; }
|
||||||
|
|
||||||
|
curMods[mod.id] = { mod, domainList };
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter out all of the modules that are exactly the same including domainList
|
||||||
|
// since there is no required action to transition.
|
||||||
|
Object.keys(prevMods).map(function (id) {
|
||||||
|
if (equal(prevMods[id], curMods[id])) {
|
||||||
|
delete prevMods[id];
|
||||||
|
delete curMods[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {prevMods, curMods};
|
||||||
|
}
|
||||||
|
async function cleanOldDns(prevConf) {
|
||||||
|
var {prevMods, curMods} = getModuleDiffs(prevConf);
|
||||||
|
|
||||||
|
// Then remove DNS records for the domains that we are no longer responsible for.
|
||||||
|
await Promise.all(Object.values(prevMods).map(function ({mod, domainList}) {
|
||||||
|
var oldDomains;
|
||||||
|
if (!curMods[mod.id] || mod.tokenId !== curMods[mod.id].mod.tokenId) {
|
||||||
|
oldDomains = domainList.slice();
|
||||||
|
} else {
|
||||||
|
oldDomains = domainList.filter(function (domain) {
|
||||||
|
return curMods[mod.id].domainList.indexOf(domain) < 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (conf.debug) {
|
||||||
|
console.log('removing old domains for module', mod.id, oldDomains.join(', '));
|
||||||
|
}
|
||||||
|
if (!oldDomains.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSession(mod.tokenId).then(function (session) {
|
||||||
|
return dnsCtrl.removeDomains(session, oldDomains);
|
||||||
|
});
|
||||||
|
}).filter(Boolean));
|
||||||
|
}
|
||||||
|
async function setNewDns(prevConf) {
|
||||||
|
var {prevMods, curMods} = getModuleDiffs(prevConf);
|
||||||
|
|
||||||
|
// And add DNS records for any newly added domains.
|
||||||
|
await Promise.all(Object.values(curMods).map(function ({mod, domainList}) {
|
||||||
|
var newDomains;
|
||||||
|
if (!prevMods[mod.id] || mod.tokenId !== prevMods[mod.id].mod.tokenId) {
|
||||||
|
newDomains = domainList.slice();
|
||||||
|
} else {
|
||||||
|
newDomains = domainList.filter(function (domain) {
|
||||||
|
return prevMods[mod.id].domainList.indexOf(domain) < 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (conf.debug) {
|
||||||
|
console.log('adding new domains for module', mod.id, newDomains.join(', '));
|
||||||
|
}
|
||||||
|
if (!newDomains.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getSession(mod.tokenId).then(function (session) {
|
||||||
|
return dnsCtrl.setDeviceAddress(session, publicAddress, newDomains);
|
||||||
|
});
|
||||||
|
}).filter(Boolean));
|
||||||
|
}
|
||||||
|
|
||||||
recheckPubAddr();
|
recheckPubAddr();
|
||||||
setInterval(recheckPubAddr, 5*60*1000);
|
setInterval(recheckPubAddr, 5*60*1000);
|
||||||
|
|
||||||
|
@ -189,17 +271,30 @@ module.exports.create = function (deps, conf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tunnelActive) {
|
if (!curConf) {
|
||||||
if (!curConf || !equal(curConf.ddns.tunnel, conf.ddns.tunnel)) {
|
|
||||||
disconnectTunnel().then(connectTunnel);
|
|
||||||
} else {
|
|
||||||
checkTunnelTokens();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to make a deep copy of the config so we can use it next time to
|
// We need to make a deep copy of the config so we can use it next time to
|
||||||
// compare and see what setup/cleanup is needed to adapt to the changes.
|
// compare and see what setup/cleanup is needed to adapt to the changes.
|
||||||
curConf = JSON.parse(JSON.stringify(conf));
|
curConf = JSON.parse(JSON.stringify(conf));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanOldDns(curConf).then(function () {
|
||||||
|
if (!tunnelActive) {
|
||||||
|
return setNewDns(curConf);
|
||||||
|
}
|
||||||
|
if (equal(curConf.ddns.tunnel, conf.ddns.tunnel)) {
|
||||||
|
return checkTunnelTokens();
|
||||||
|
} else {
|
||||||
|
return disconnectTunnel().then(connectTunnel);
|
||||||
|
}
|
||||||
|
}).catch(function (err) {
|
||||||
|
console.error('error transitioning DNS between configurations');
|
||||||
|
console.error(err);
|
||||||
|
}).then(function () {
|
||||||
|
// We need to make a deep copy of the config so we can use it next time to
|
||||||
|
// compare and see what setup/cleanup is needed to adapt to the changes.
|
||||||
|
curConf = JSON.parse(JSON.stringify(conf));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
updateConf();
|
updateConf();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue