Skip to content

Instantly share code, notes, and snippets.

@Marak
Forked from creationix/.gitignore
Created August 8, 2012 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Marak/3297582 to your computer and use it in GitHub Desktop.
Save Marak/3297582 to your computer and use it in GitHub Desktop.
node_modules
secrets.js
{
"name": "node-nat-ddns-cron",
"private": true,
"version": "0.0.0",
"dependencies": {
"nat-pmp": "0.0.1"
}
}
var natpmp = require('nat-pmp');
var https = require('https');
var encode = require('querystring').encode;
// This is my linode API key, not stored in this file for obvious reasons.
var apiKey = require('./secrets').apiKey;
var client = natpmp.connect('10.0.1.1');
console.log("Looking up external IP address...");
client.externalIp(function (err, data) {
if (err) throw err;
// console.log("external ip", data);
var ip = data.ip.join(".");
console.log("Updating dns for home.creationix.com to point to %s...", ip);
setHost("creationix.com", "home", ip, function (err, result) {
if (err) throw err;
console.log("Mapping 22 on the local machine to 2222 on the nat...")
client.portMapping({ private:22, public: 2222, ttl: 3600}, function (err, result) {
if (err) throw err;
console.log("Done");
process.exit();
});
});
});
///////////////////////////////////////////////////////////////////////////////
function request(query, callback) {
query.api_key = "...";
var path = "/?" + encode(query);
// console.log("GET https://api.linode.com" + path);
query.api_key = apiKey;
var path = "/?" + encode(query);
https.request({
host: "api.linode.com",
path: path
}, function (res) {
var parts = [];
var length = 0;
res.on("data", function (chunk) {
parts.push(chunk);
length += chunk.length;
});
res.on("end", function () {
res.rawBody = Buffer.concat(parts, length);
try {
res.body = JSON.parse(res.rawBody.toString('utf8'));
}
catch (err) {
return callback(err);
}
var errors = res.body.ERRORARRAY;
if (errors.length) {
var error = errors[0];
var err = new Error(error.ERRORMESSAGE);
err.linodeCode = error.ERRORCODE;
return callback(err, res);
}
return callback(null, res, res.body.DATA);
});
}).end();
}
function filter(data, query) {
var queryKeys = Object.keys(query);
var queryKeysLength = queryKeys.length;
return data.filter(function (item) {
for (var j = 0; j < queryKeysLength; j++) {
var key = queryKeys[j];
if (item[key] !== query[key]) {
return false;
}
}
return true;
});
}
function getDomains(query, callback) {
request({api_action: "domain.list"}, function (err, res, data) {
if (err) return callback(err);
var domains = filter(data, query);
callback(null, domains);
});
}
function getDomain(query, callback) {
getDomains(query, function (err, domains) {
if (domains.length) {
return callback(null, domains[0]);
}
var err = new Error("No domain found using query " + JSON.stringify(query));
callback(err);
});
}
function getDomainResources(domainId, query, callback) {
request({
api_action: "domain.resource.list",
DomainID: domainId
}, function (err, res, data) {
if (err) return callback(err);
var resources = filter(data, query);
callback(null, resources);
});
}
function getDomainResource(domainId, query, callback) {
getDomainResources(domainId, query, function (err, resources) {
if (resources.length) {
return callback(null, resources[0]);
}
var err = new Error("No resource found on domain " + domainId + " using query " + JSON.stringify(query));
callback(err);
});
}
function updateDomainResource(domainId, resourceId, values, callback) {
var query = {
api_action: "domain.resource.update",
DomainID: domainId,
ResourceID: resourceId
};
for (var key in values) {
query[key] = values[key];
}
request(query, function (err, res, data) {
if (err) return callback(err);
callback(null, data);
});
}
function setHost(domainName, subdomain, ip, callback) {
getDomain({DOMAIN: domainName}, function (err, domain) {
if (err) return callback(err);
// console.log("domain", domain);
var domainId = domain.DOMAINID;
getDomainResource(domainId, {TYPE: "a", NAME: subdomain}, function (err, resource) {
if (err) return callback(err);
// console.log("resource", resource);
var resourceId = resource.RESOURCEID;
updateDomainResource(domainId, resourceId, { Target: ip }, callback);
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment