forked from coolaj86/goldilocks.js
		
	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)) {
 | 
					      // We need to make a deep copy of the config so we can use it next time to
 | 
				
			||||||
        disconnectTunnel().then(connectTunnel);
 | 
					      // compare and see what setup/cleanup is needed to adapt to the changes.
 | 
				
			||||||
      } else {
 | 
					      curConf = JSON.parse(JSON.stringify(conf));
 | 
				
			||||||
        checkTunnelTokens();
 | 
					      return;
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We need to make a deep copy of the config so we can use it next time to
 | 
					    cleanOldDns(curConf).then(function () {
 | 
				
			||||||
    // compare and see what setup/cleanup is needed to adapt to the changes.
 | 
					      if (!tunnelActive) {
 | 
				
			||||||
    curConf = JSON.parse(JSON.stringify(conf));
 | 
					        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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user