107 lines
3.3 KiB
JavaScript
107 lines
3.3 KiB
JavaScript
import opts from 'config'
|
|
import Notifier from '@uci-utils/notify'
|
|
import Route53 from '@uci-utils/route53'
|
|
import pIp from 'public-ip'
|
|
import { lookup as clookup } from 'dns'
|
|
import { promisify } from 'util'
|
|
const lookup = promisify(clookup)
|
|
import { CronJob } from 'cron'
|
|
import to from 'await-to-js'
|
|
import { info } from 'console'
|
|
|
|
const rname = process.argv[2] || opts.domain
|
|
if (!rname) {
|
|
console.log('exiting, must supply (sub)domain record name to check')
|
|
console.log(JSON.stringify(opts, null, 3))
|
|
process.exit()
|
|
}
|
|
|
|
const verbose = (opts.verbose ||'').length
|
|
const interval = (opts.lookup || {}).interval || 10 // seconds
|
|
const timeout = (opts.lookup || {}).timeout || 5 // minutes
|
|
|
|
if (verbose) console.log(JSON.stringify(opts, null, 3))
|
|
|
|
let notify=()=>{} // noop
|
|
const route53 = new Route53(opts.aws ? opts.aws : {profile:'default'})
|
|
;
|
|
(async () => {
|
|
if (opts.notify){
|
|
const notifier = await Notifier.create(opts.notify)
|
|
notify = notifier.send.bind(notifier)
|
|
}
|
|
if (opts.cron && !opts.debug) {
|
|
console.log('setting up check cron job every', opts.cron,'minutes')
|
|
const cronstr = `0 */${opts.cron} * * * *`
|
|
const job = new CronJob(cronstr, checkIP)
|
|
console.log('cron job starting with:',cronstr)
|
|
job.start()
|
|
} else {
|
|
console.log('running check a single time')
|
|
checkIP()
|
|
}
|
|
|
|
})().catch(err => {
|
|
console.log('FATAL: IP Updater! \n',err)
|
|
process.exitCode = 1
|
|
process.kill(process.pid, 'SIGINT') // this will restart via systemd unit
|
|
})
|
|
|
|
|
|
async function checkIP () {
|
|
let curr = await pIp.v4()
|
|
if (opts.dev) {
|
|
let ip = curr.split('.')
|
|
ip[0] = ip[0] - Math.floor(Math.random() * 10)
|
|
curr = ip.join('.')
|
|
console.log('development run: generated dummy current ip', curr)
|
|
}
|
|
const saved = await route53.getZoneRecordValue(rname)
|
|
if (opts.debug) notify('checking for change in public ip',timestamp())
|
|
if (curr !== saved) {
|
|
let msg=`${timestamp()} Network:${opts.network}, a new public ip has been detected for ${rname} from ${saved} to ${curr}`
|
|
console.log(msg)
|
|
notify(msg)
|
|
const res=JSON.stringify(await route53.updateZoneRecordValue(rname,curr),null,3)
|
|
console.log(res)
|
|
notify(res)
|
|
const fail = setTimeout(()=>{
|
|
clearInterval(check)
|
|
msg=`${timestamp()}, ${opts.network}: FATAL the pending change of ip address was not realized in ${timeout} minutes. Human attention required`
|
|
console.log(msg)
|
|
notify(msg)
|
|
},timeout*1000*60)
|
|
const check = setInterval(async ()=>{
|
|
let [err,info] = await to(lookup(rname))
|
|
if (err) {
|
|
clearInterval(check)
|
|
clearTimeout(fail)
|
|
msg=`FATAL Error in lookup of' ${rname}, ${err}, aborting check, human intervention required`
|
|
console.log(msg)
|
|
notify(msg)
|
|
} else {
|
|
if (curr === info.address) {
|
|
msg=`Update Succeeded, lookup of ${rname} is now ${curr}`
|
|
clearInterval(check)
|
|
clearTimeout(fail)
|
|
console.log(msg)
|
|
notify(msg)
|
|
} else {
|
|
msg=`Update Pending, will check again in ${interval} seconds`
|
|
if (verbose || opts.debug ) {
|
|
notify(msg)
|
|
console.log(msg)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
,interval*1000)
|
|
|
|
} else console.log('Public IP has not changed, nothing to do', saved)
|
|
|
|
}
|
|
|
|
function timestamp() {
|
|
return new Date().toLocaleString().replace('T', ' ').substring(0, 19)
|
|
}
|