diff --git a/docker-compose.yml b/docker-compose.yml index 801f795..5971183 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,6 @@ services: environment: - API_KEY=123 - ZONE_ID=023e105f4ecef8ad9ca31a8372d0c353 - - DOMAIN_NAME=dyndns.example.com + - DOMAIN_NAMES=dyndns.example.com,example.com - INTERVAL=5 - LOG_LEVEL=INFO diff --git a/src/cloudflare.ts b/src/cloudflare.ts index bbd5f5f..9d06c86 100644 --- a/src/cloudflare.ts +++ b/src/cloudflare.ts @@ -17,7 +17,7 @@ const getDnsRecord = async ( name: string, type: string, apiKey: string, -): Promise<{ content: string; id: string }> => { +): Promise<{ content: string; name: string; id: string }> => { const url = `https://api.cloudflare.com/client/v4/zones/${zoneIdentifier}/dns_records?name=${name}&type=${type}`; const headers = { @@ -28,7 +28,7 @@ const getDnsRecord = async ( const json: CFResponse = await response.json(); if (json.success) { - return (({ content, id }) => ({ content, id }))(json.result[0]); + return (({ content, name, id }) => ({ content, name, id }))(json.result[0]); } const error = json.errors.reduce( @@ -40,6 +40,16 @@ const getDnsRecord = async ( ); }; +const getDnsRecords = async ( + zoneIdentifier: string, + names: string[], + type: string, + apiKey: string, +): Promise<{ content: string; name: string; id: string }[]> => + await Promise.all( + names.map(async (name) => getDnsRecord(zoneIdentifier, name, type, apiKey)), + ); + const patchDnsRecord = async ( zoneIdentifier: string, identifier: string, @@ -77,4 +87,22 @@ const patchDnsRecord = async ( ); }; -export { getDnsRecord, patchDnsRecord }; +const patchDnsRecords = async ( + dnsRecords: { content: string; name: string; id: string }[], + zoneIdentifier: string, + apiKey: string, + content: string, + type: string, +) => + dnsRecords.forEach(async (dnsRecord) => + await patchDnsRecord( + zoneIdentifier, + dnsRecord.id, + apiKey, + content, + dnsRecord.name, + type, + ) + ); + +export { getDnsRecord, getDnsRecords, patchDnsRecord, patchDnsRecords }; diff --git a/src/index.ts b/src/index.ts index 657f56a..cfc1682 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,49 +1,55 @@ -import { getDnsRecord, patchDnsRecord } from "./cloudflare"; +import { getDnsRecords, patchDnsRecords } from "./cloudflare"; import getPublicIp from "./getPublicIp"; import * as log from "./log"; -const { ZONE_ID, DOMAIN_NAME, API_KEY, INTERVAL } = process.env; +const { ZONE_ID, DOMAIN_NAMES, API_KEY, INTERVAL } = process.env; if (ZONE_ID === undefined) { log.error("could not access environment variable 'ZONE_ID'"); } -if (DOMAIN_NAME === undefined) { - log.error("could not access environment variable 'DOMAIN_NAME'"); +if (DOMAIN_NAMES === undefined) { + log.error("could not access environment variable 'DOMAIN_NAMES'"); } if (API_KEY === undefined) { log.error("could not access environment variable 'API_KEY'"); } if ( - ZONE_ID === undefined || DOMAIN_NAME === undefined || API_KEY === undefined + ZONE_ID === undefined || DOMAIN_NAMES === undefined || API_KEY === undefined ) { process.exit(1); } const dynamicDns = async () => { + const domainNames = DOMAIN_NAMES.split(","); try { - const [publicIp, dnsRecord] = await Promise.all([ + const [publicIp, dnsRecords] = await Promise.all([ getPublicIp(), - getDnsRecord(ZONE_ID, DOMAIN_NAME, "A", API_KEY), + getDnsRecords(ZONE_ID, domainNames, "A", API_KEY), ]); - if (publicIp === dnsRecord.content) { + const dnsRecordsToPatch = dnsRecords.filter((dnsRecord) => { + dnsRecord.content !== publicIp; + }); + + if (dnsRecordsToPatch.length === 0) { log.info(`public ip address remained at '${publicIp}', no patch needed`); log.info(`checking again in ${INTERVAL} minutes\n`); return; } log.info( - `public ip address changed from '${dnsRecord.content}' to '${publicIp}'`, + `public ip address changed from '${ + dnsRecordsToPatch[0].content + }' to '${publicIp}'`, ); - await patchDnsRecord( + await patchDnsRecords( + dnsRecordsToPatch, ZONE_ID, - dnsRecord.id, API_KEY, publicIp, - DOMAIN_NAME, "A", ); - log.info("patched dns entry"); + log.info("patched dns entries"); log.info(`checking again in ${INTERVAL} minutes\n`); } catch (error) { log.error((error as Error).message); diff --git a/src/log.ts b/src/log.ts index b1dde29..0ea38e2 100644 --- a/src/log.ts +++ b/src/log.ts @@ -6,7 +6,7 @@ const STYLES = { ERROR: "\x1b[31m", }; -let LOG_LEVEL = process.env.LOG_LEVEL || "INFO"; +let LOG_LEVEL = process.env.LOG_LEVEL ?? "INFO"; if (!["DEBUG", "INFO", "WARN", "ERROR"].includes(LOG_LEVEL)) { console.warn(