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 = {}; | ||||
|       resp.data.forEach(function (tldInfo) { | ||||
|         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.
 | ||||
|       return { | ||||
|         tld: split.slice(-tldSegCnt).join('.') | ||||
|       , sld: split.slice(-tldSegCnt-1, 1) | ||||
|       , sub: split.slice(0, -tldSegCnt-1) | ||||
|       , sld: split.slice(-tldSegCnt-1, -tldSegCnt).join('.') | ||||
|       , sub: split.slice(0, -tldSegCnt-1).join('.') | ||||
|       }; | ||||
|     }); | ||||
|   } | ||||
| @ -152,8 +152,23 @@ module.exports.create = function (deps, conf) { | ||||
|     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 { | ||||
|     getDeviceAddresses: getDeviceAddresses | ||||
|   , setDeviceAddress:   setDeviceAddress | ||||
|     getDeviceAddresses | ||||
|   , setDeviceAddress | ||||
|   , removeDomains | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| @ -8,12 +8,13 @@ module.exports.create = function (deps, conf) { | ||||
| 
 | ||||
|   var loopbackDomain; | ||||
| 
 | ||||
|   function iterateAllModules(action) { | ||||
|     var promises = conf.ddns.modules.map(function (mod) { | ||||
|   function iterateAllModules(action, curConf) { | ||||
|     curConf = curConf || conf; | ||||
|     var promises = curConf.ddns.modules.map(function (mod) { | ||||
|       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) { | ||||
|         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(); | ||||
|   setInterval(recheckPubAddr, 5*60*1000); | ||||
| 
 | ||||
| @ -189,17 +271,30 @@ module.exports.create = function (deps, conf) { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (tunnelActive) { | ||||
|       if (!curConf || !equal(curConf.ddns.tunnel, conf.ddns.tunnel)) { | ||||
|         disconnectTunnel().then(connectTunnel); | ||||
|       } else { | ||||
|         checkTunnelTokens(); | ||||
|       } | ||||
|     if (!curConf) { | ||||
|       // 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)); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     // 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)); | ||||
|     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(); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user