Created
December 28, 2014 15:56
-
-
Save highwaycoder/18dce21b0b018a33e470 to your computer and use it in GitHub Desktop.
Update a DNS record using the Digital Ocean REST API. Configure using the constants at the top, run using "node update-dns". NB: borrows heavily from the PHP version from @bensquire called Digital-Ocean-Dynamic-DNS-Updater
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ACCESS_TOKEN = ''; | |
const DOMAIN = ''; | |
const RECORD = ''; | |
var http = require('http'); | |
var https = require('https'); | |
var when = require('when'); | |
var color = require('bash-color'); | |
var fetchExternalIp = function () { | |
process.stdout.write('Fetching external ip...'); | |
return when.promise(function (resolve, reject) { | |
var request = http.get("http://ipecho.net/plain", function (result) { | |
var ip = ""; | |
result.on('data', function (chunk) { | |
ip += chunk; | |
}); | |
result.on('end', function () { | |
resolve(ip); | |
}); | |
}); | |
}); | |
}; | |
var verifyExternalIp = function (ip) { | |
return when.promise(function (resolve, reject) { | |
// IP address regex fetched from http://www.regular-expressions.info/examples.html | |
if (/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/.test(ip)) { | |
process.stdout.write(color.green(ip + '\n')); | |
resolve(ip); | |
} else { | |
process.stdout.write(color.red('[FAIL]' + '\n')); | |
reject('bad ip address'); | |
} | |
}); | |
}; | |
var errorHandler = function (error) { | |
process.stderr.write('Error: ' + error); | |
}; | |
var fetchCurrentRecord = function (newIp) { | |
process.stdout.write("Fetching current record..."); | |
return when.promise(function (resolve, reject) { | |
// "https://api.digitalocean.com/v2/domains/" + DOMAIN + "/records" | |
var request = https.get({ | |
hostname: "api.digitalocean.com", | |
port: 443, | |
path: "/v2/domains/" + DOMAIN + "/records", | |
headers: { | |
"Authorization": "Bearer " + ACCESS_TOKEN, | |
"Accept": "application/json" | |
} | |
}, function (result) { | |
var jsonResult = ""; | |
result.on('data', function (chunk) { | |
jsonResult += chunk; | |
}); | |
result.on('end', function () { | |
var records = JSON.parse(jsonResult).domain_records; | |
var findDomain = function (currentRecord) { | |
return currentRecord.name === RECORD; | |
}; | |
var validRecords = records.filter(findDomain); | |
if (validRecords.length != 1) { | |
process.stdout.write(color.red("[FAIL]") + "\n"); | |
reject('Too many or too few valid records: ', validRecords.length); | |
} else { | |
var currentIp = validRecords[0].data; | |
var recordId = validRecords[0].id | |
process.stdout.write(color.green(currentIp) + "\n"); | |
resolve({ | |
currentIp: currentIp, | |
newIp: newIp, | |
recordId: recordId | |
}); | |
} | |
}); | |
}); | |
}); | |
}; | |
var verifyCurrentRecord = function (args) { | |
process.stdout.write("Verifying new ip is different from old ip..."); | |
return when.promise(function (resolve, reject) { | |
if (args.currentIp === args.newIp) { | |
process.stdout.write(color.yellow("MATCH") + "\n"); | |
resolve(false); | |
} else { | |
process.stdout.write(color.green("NO MATCH") + "\n"); | |
resolve(args); | |
} | |
}); | |
}; | |
var updateRecord = function (args) { | |
return when.promise(function (resolve, reject) { | |
var requestBody = { | |
data: args.newIp | |
}; | |
var requestBodyStr = JSON.stringify(requestBody); | |
var req = https.request({ | |
hostname: "api.digitalocean.com", | |
port: 443, | |
method: 'PUT', | |
path: "v2/domains/" + DOMAIN + "/records/" + args.recordId, | |
headers: { | |
"Authorization": "Bearer " + ACCESS_TOKEN, | |
"Content-Type": "application/json", | |
"Content-Length": requestBodyStr.length | |
} | |
}); | |
req.write(requestBodyStr); | |
req.end(); | |
}); | |
} | |
var maybeUpdateRecord = function (newIp, recordId) { | |
return when.promise(function (resolve, reject) { | |
if(newIp !== false) { | |
process.stdout.write("Updating record..."); | |
updateRecord(newIp, recordId).then(resolve, reject); | |
} else { | |
process.stdout.write("Doing nothing (already up-to-date)\n"); | |
} | |
}); | |
} | |
var run = function () { | |
process.stdout.write('Updating record: ' + RECORD + '.' + DOMAIN + ' at ' + (new Date()).toISOString() + '\n'); | |
fetchExternalIp() | |
.then(verifyExternalIp) | |
.then(fetchCurrentRecord) | |
.then(verifyCurrentRecord) | |
.then(maybeUpdateRecord) | |
.catch(errorHandler) | |
; | |
}; | |
// finally, run the damn script | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment