diff --git a/src/apptask.js b/src/apptask.js index 29cb22fbc..f61787954 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -54,7 +54,6 @@ var addons = require('./addons.js'), superagent = require('superagent'), sysinfo = require('./sysinfo.js'), util = require('util'), - waitForDns = require('./waitfordns.js'), _ = require('underscore'); var COLLECTD_CONFIG_EJS = fs.readFileSync(__dirname + '/collectd.config.ejs', { encoding: 'utf8' }), @@ -297,25 +296,10 @@ function waitForDnsPropagation(app, callback) { return callback(null); } - async.retry({ interval: 5000, times: 120 }, function checkStatus(retryCallback) { - subdomains.status(app.dnsRecordId, function (error, result) { - if (error) return retryCallback(new Error('Failed to get dns record status : ' + error.message)); - - debugApp(app, 'waitForDnsPropagation: dnsRecordId:%s status:%s', app.dnsRecordId, result); - - if (result !== 'done') return retryCallback(new Error(util.format('app:%s not ready yet: %s', app.id, result))); - - retryCallback(null); - }); - }, function (error) { + sysinfo.getIp(function (error, ip) { if (error) return callback(error); - // finally validate with waitForDns - sysinfo.getIp(function (error, ip) { - if (error) return callback(error); - - waitForDns(config.appFqdn(app.location), ip, 'A', { interval: 5000, times: 30 }, callback); - }); + subdomains.waitForDns(config.appFqdn(app.location), ip, 'A', { interval: 5000, times: 120 }, callback); }); } @@ -324,7 +308,7 @@ function waitForAltDomainDnsPropagation(app, callback) { // try for 10 minutes before giving up. this allows the user to "reconfigure" the app in the case where // an app has an external domain and cloudron is migrated to custom domain. - waitForDns(app.altDomain, config.appFqdn(app.location), 'CNAME', { interval: 10000, times: 60 }, callback); + subdomains.waitForDns(app.altDomain, config.appFqdn(app.location), 'CNAME', { interval: 10000, times: 60 }, callback); } // updates the app object and the database diff --git a/src/certificates.js b/src/certificates.js index 7052add51..6a3aa880f 100644 --- a/src/certificates.js +++ b/src/certificates.js @@ -31,10 +31,10 @@ var acme = require('./cert/acme.js'), paths = require('./paths.js'), safe = require('safetydance'), settings = require('./settings.js'), + subdomains = require('./subdomains.js'), sysinfo = require('./sysinfo.js'), user = require('./user.js'), util = require('util'), - waitForDns = require('./waitfordns.js'), x509 = require('x509'); function CertificatesError(reason, errorOrMessage) { @@ -102,7 +102,7 @@ function installAdminCertificate(callback) { sysinfo.getIp(function (error, ip) { if (error) return callback(error); - waitForDns(config.adminFqdn(), ip, 'A', { interval: 30000, times: 50000 }, function (error) { + subdomains.waitForDns(config.adminFqdn(), ip, 'A', { interval: 30000, times: 50000 }, function (error) { if (error) return callback(error); ensureCertificate({ location: constants.ADMIN_LOCATION }, function (error, certFilePath, keyFilePath) { diff --git a/src/dns/caas.js b/src/dns/caas.js index a0693f653..c51a2ef2d 100644 --- a/src/dns/caas.js +++ b/src/dns/caas.js @@ -4,7 +4,8 @@ exports = module.exports = { upsert: upsert, get: get, del: del, - getChangeStatus: getChangeStatus + getChangeStatus: getChangeStatus, + waitForDns: require('./waitfordns.js') }; var assert = require('assert'), diff --git a/src/dns/digitalocean.js b/src/dns/digitalocean.js index 784dbbede..bed6a73f7 100644 --- a/src/dns/digitalocean.js +++ b/src/dns/digitalocean.js @@ -4,7 +4,8 @@ exports = module.exports = { upsert: upsert, get: get, del: del, - getChangeStatus: getChangeStatus + getChangeStatus: getChangeStatus, + waitForDns: require('./waitfordns.js') }; var assert = require('assert'), diff --git a/src/dns/interface.js b/src/dns/interface.js index 227d35b9f..404b9082e 100644 --- a/src/dns/interface.js +++ b/src/dns/interface.js @@ -10,7 +10,8 @@ exports = module.exports = { upsert: upsert, get: get, del: del, - getChangeStatus: getChangeStatus + getChangeStatus: getChangeStatus, + waitForDns: require('./waitfordns.js') }; var assert = require('assert'), diff --git a/src/dns/noop.js b/src/dns/noop.js index df594a166..1a654bba3 100644 --- a/src/dns/noop.js +++ b/src/dns/noop.js @@ -4,7 +4,8 @@ exports = module.exports = { upsert: upsert, get: get, del: del, - getChangeStatus: getChangeStatus + getChangeStatus: getChangeStatus, + waitForDns: require('./waitfordns.js') }; var assert = require('assert'), diff --git a/src/dns/route53.js b/src/dns/route53.js index 53198e3ee..41194be42 100644 --- a/src/dns/route53.js +++ b/src/dns/route53.js @@ -5,6 +5,7 @@ exports = module.exports = { get: get, del: del, getChangeStatus: getChangeStatus, + waitForDns: require('./waitfordns.js'), // not part of "dns" interface getHostedZone: getHostedZone diff --git a/src/waitfordns.js b/src/dns/waitfordns.js similarity index 92% rename from src/waitfordns.js rename to src/dns/waitfordns.js index e0eb31aaa..3fc06e647 100644 --- a/src/waitfordns.js +++ b/src/dns/waitfordns.js @@ -4,8 +4,9 @@ exports = module.exports = waitForDns; var assert = require('assert'), async = require('async'), - debug = require('debug')('box:src/waitfordns'), + debug = require('debug')('box:dns/waitfordns'), dns = require('native-dns'), + SubdomainError = require('../subdomains.js').SubdomainError, tld = require('tldjs'); // the first arg to callback is not an error argument; this is required for async.every @@ -80,12 +81,12 @@ function waitForDns(domain, value, type, options, callback) { debug('waitForDNS: %s attempt %s.', domain, attempt++); dns.resolveNs(zoneName, function (error, nameservers) { - if (error || !nameservers) return retryCallback(error || new Error('Unable to get nameservers')); + if (error || !nameservers) return retryCallback(error || new SubdomainError(SubdomainError.EXTERNAL_ERROR, 'Unable to get nameservers')); async.every(nameservers, isChangeSynced.bind(null, domain, value, type), function (synced) { debug('waitForIp: %s %s ns: %j', domain, synced ? 'done' : 'not done', nameservers); - retryCallback(synced ? null : new Error('ETRYAGAIN')); + retryCallback(synced ? null : new SubdomainError(SubdomainError.EXTERNAL_ERROR, 'ETRYAGAIN')); }); }); }, function retryDone(error) { diff --git a/src/subdomains.js b/src/subdomains.js index 376be5b10..bdd028a24 100644 --- a/src/subdomains.js +++ b/src/subdomains.js @@ -5,18 +5,15 @@ module.exports = exports = { status: status, upsert: upsert, get: get, + waitForDns: waitForDns, SubdomainError: SubdomainError }; var assert = require('assert'), - caas = require('./dns/caas.js'), config = require('./config.js'), - digitalocean = require('./dns/digitalocean.js'), - route53 = require('./dns/route53.js'), settings = require('./settings.js'), - util = require('util'), - noopDns = require('./dns/noop.js'); + util = require('util'); function SubdomainError(reason, errorOrMessage) { assert.strictEqual(typeof reason, 'string'); @@ -51,10 +48,10 @@ function api(provider) { assert.strictEqual(typeof provider, 'string'); switch (provider) { - case 'caas': return caas; - case 'route53': return route53; - case 'digitalocean': return digitalocean; - case 'noop': return noopDns; + case 'caas': return require('./dns/caas.js'); + case 'route53': return require('./dns/route53.js'); + case 'digitalocean': return require('./dns/digitalocean.js'); + case 'noop': return require('./dns/noop.js'); default: return null; } } @@ -109,6 +106,20 @@ function remove(subdomain, type, values, callback) { }); } +function waitForDns(domain, value, type, options, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof value, 'string'); + assert(type === 'A' || type === 'CNAME'); + assert(options && typeof options === 'object'); // { interval: 5000, times: 50000 } + assert.strictEqual(typeof callback, 'function'); + + settings.getDnsConfig(function (error, dnsConfig) { + if (error) return callback(new SubdomainError(SubdomainError.INTERNAL_ERROR, error)); + + api(dnsConfig.provider).waitForDns(domain, value, type, options, callback); + }); +} + function status(changeId, callback) { assert.strictEqual(typeof changeId, 'string'); assert.strictEqual(typeof callback, 'function');