dns: refactor register/unregisterLocation logic
this prepares it for ipv6 support
This commit is contained in:
+42
-40
@@ -195,6 +195,30 @@ function makeWildcard(vhost) {
|
||||
return parts.join('.');
|
||||
}
|
||||
|
||||
async function registerLocation(location, options, recordType, recordValue) {
|
||||
const overwriteDns = options.overwriteDns || false;
|
||||
|
||||
// get the current record before updating it
|
||||
const [getError, values] = await safe(getDnsRecords(location.subdomain, location.domain, recordType));
|
||||
if (getError) {
|
||||
const retryable = getError.reason !== BoxError.ACCESS_DENIED && getError.reason !== BoxError.NOT_FOUND;
|
||||
debug(`registerLocation: Get error. retryable: ${retryable}. ${upsertError.message}`);
|
||||
throw new BoxError(getError.reason, getError.message, { domain: location, retryable });
|
||||
}
|
||||
|
||||
if (values.length === 1 && values[0] === recordValue) return; // up-to-date
|
||||
|
||||
// refuse to update any existing DNS record for custom domains that we did not create
|
||||
if (values.length !== 0 && !overwriteDns) throw new BoxError(BoxError.ALREADY_EXISTS, `DNS ${recordType} record already exists`, { domain: location, retryable: false });
|
||||
|
||||
const [upsertError] = await safe(upsertDnsRecords(location.subdomain, location.domain, recordType, [ recordValue ]));
|
||||
if (upsertError) {
|
||||
const retryable = upsertError.reason === BoxError.BUSY || upsertError.reason === BoxError.EXTERNAL_ERROR;
|
||||
debug(`registerLocation: Upsert error. retryable: ${retryable}. ${upsertError.message}`);
|
||||
throw new BoxError(BoxError.EXTERNAL_ERROR, upsertError.message, { domain: location, retryable });
|
||||
}
|
||||
}
|
||||
|
||||
async function registerLocations(locations, options, progressCallback) {
|
||||
assert(Array.isArray(locations));
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
@@ -202,61 +226,39 @@ async function registerLocations(locations, options, progressCallback) {
|
||||
|
||||
debug(`registerLocations: Will register ${JSON.stringify(locations)} with options ${JSON.stringify(options)}`);
|
||||
|
||||
const overwriteDns = options.overwriteDns || false;
|
||||
|
||||
const ip = await sysinfo.getServerIPv4();
|
||||
const ipv4 = await sysinfo.getServerIPv4();
|
||||
|
||||
for (const location of locations) {
|
||||
const error = await promiseRetry({ times: 200, interval: 5000, debug }, async function () { // returns error to abort the "retry"
|
||||
progressCallback({ message: `Registering location: ${location.subdomain ? (location.subdomain + '.') : ''}${location.domain}` });
|
||||
progressCallback({ message: `Registering location: ${location.subdomain ? (location.subdomain + '.') : ''}${location.domain}` });
|
||||
|
||||
// get the current record before updating it
|
||||
const [error, values] = await safe(getDnsRecords(location.subdomain, location.domain, 'A'));
|
||||
if (error && error.reason === BoxError.EXTERNAL_ERROR) throw new BoxError(BoxError.EXTERNAL_ERROR, error.message, { domain: location }); // try again
|
||||
// give up for other errors
|
||||
if (error && error.reason === BoxError.ACCESS_DENIED) return new BoxError(BoxError.ACCESS_DENIED, error.message, { domain: location });
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return new BoxError(BoxError.NOT_FOUND, error.message, { domain: location });
|
||||
if (error) return new BoxError(BoxError.EXTERNAL_ERROR, error.message, location);
|
||||
|
||||
if (values.length !== 0 && values[0] === ip) return null; // up-to-date
|
||||
|
||||
// refuse to update any existing DNS record for custom domains that we did not create
|
||||
if (values.length !== 0 && !overwriteDns) return new BoxError(BoxError.ALREADY_EXISTS, 'DNS Record already exists', { domain: location });
|
||||
|
||||
const [upsertError] = await safe(upsertDnsRecords(location.subdomain, location.domain, 'A', [ ip ]));
|
||||
if (upsertError && (upsertError.reason === BoxError.BUSY || upsertError.reason === BoxError.EXTERNAL_ERROR)) {
|
||||
progressCallback({ message: `registerSubdomains: Upsert error. Will retry. ${upsertError.message}` });
|
||||
throw new BoxError(BoxError.EXTERNAL_ERROR, upsertError.message, { domain: location }); // try again
|
||||
}
|
||||
|
||||
return upsertError ? new BoxError(BoxError.EXTERNAL_ERROR, upsertError.message, location) : null;
|
||||
await promiseRetry({ times: 200, interval: 5000, debug, retry: (error) => error.retryable }, async function () {
|
||||
await registerLocation(location, options, 'A', ipv4);
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function unregisterLocation(location, recordType, recordValue) {
|
||||
const [error] = await safe(removeDnsRecords(location.subdomain, location.domain, recordType, [ recordValue ]));
|
||||
if (!error || error.reason === BoxError.NOT_FOUND) return;
|
||||
|
||||
const retryable = error.reason === BoxError.BUSY || error.reason === BoxError.EXTERNAL_ERROR;
|
||||
debug(`unregisterLocation: Error unregistering location ${recordType}. retryable: ${retryable}. ${error.message}`);
|
||||
|
||||
throw new BoxError(BoxError.EXTERNAL_ERROR, error.message, { domain: location, retryable });
|
||||
}
|
||||
|
||||
async function unregisterLocations(locations, progressCallback) {
|
||||
assert(Array.isArray(locations));
|
||||
assert.strictEqual(typeof progressCallback, 'function');
|
||||
|
||||
const ip = await sysinfo.getServerIPv4();
|
||||
const ipv4 = await sysinfo.getServerIPv4();
|
||||
|
||||
for (const location of locations) {
|
||||
const error = await promiseRetry({ times: 30, interval: 5000, debug }, async function () { // returns error to abort the "retry"
|
||||
progressCallback({ message: `Unregistering location: ${location.subdomain ? (location.subdomain + '.') : ''}${location.domain}` });
|
||||
progressCallback({ message: `Unregistering location: ${location.subdomain ? (location.subdomain + '.') : ''}${location.domain}` });
|
||||
|
||||
const [error] = await safe(removeDnsRecords(location.subdomain, location.domain, 'A', [ ip ]));
|
||||
if (error && error.reason === BoxError.NOT_FOUND) return;
|
||||
if (error && (error.reason === BoxError.BUSY || error.reason === BoxError.EXTERNAL_ERROR)) {
|
||||
progressCallback({ message: `Error unregistering location. Will retry. ${error.message}`});
|
||||
throw new BoxError(BoxError.EXTERNAL_ERROR, error.message, { domain: location }); // try again
|
||||
}
|
||||
|
||||
return error ? new BoxError(BoxError.EXTERNAL_ERROR, error.message, { domain: location }) : null; // give up for other errors
|
||||
await promiseRetry({ times: 30, interval: 5000, debug, retry: (error) => error.retryable }, async function () {
|
||||
await unregisterLocation(location, 'A', ipv4);
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user