support multiple domains
This commit is contained in:
@@ -5,6 +5,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- API_KEY=123
|
- API_KEY=123
|
||||||
- ZONE_ID=023e105f4ecef8ad9ca31a8372d0c353
|
- ZONE_ID=023e105f4ecef8ad9ca31a8372d0c353
|
||||||
- DOMAIN_NAME=dyndns.example.com
|
- DOMAIN_NAMES=dyndns.example.com,example.com
|
||||||
- INTERVAL=5
|
- INTERVAL=5
|
||||||
- LOG_LEVEL=INFO
|
- LOG_LEVEL=INFO
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const getDnsRecord = async (
|
|||||||
name: string,
|
name: string,
|
||||||
type: string,
|
type: string,
|
||||||
apiKey: string,
|
apiKey: string,
|
||||||
): Promise<{ content: string; id: string }> => {
|
): Promise<{ content: string; name: string; id: string }> => {
|
||||||
const url =
|
const url =
|
||||||
`https://api.cloudflare.com/client/v4/zones/${zoneIdentifier}/dns_records?name=${name}&type=${type}`;
|
`https://api.cloudflare.com/client/v4/zones/${zoneIdentifier}/dns_records?name=${name}&type=${type}`;
|
||||||
const headers = {
|
const headers = {
|
||||||
@@ -28,7 +28,7 @@ const getDnsRecord = async (
|
|||||||
const json: CFResponse = await response.json();
|
const json: CFResponse = await response.json();
|
||||||
|
|
||||||
if (json.success) {
|
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(
|
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 (
|
const patchDnsRecord = async (
|
||||||
zoneIdentifier: string,
|
zoneIdentifier: string,
|
||||||
identifier: 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 };
|
||||||
|
|||||||
32
src/index.ts
32
src/index.ts
@@ -1,49 +1,55 @@
|
|||||||
import { getDnsRecord, patchDnsRecord } from "./cloudflare";
|
import { getDnsRecords, patchDnsRecords } from "./cloudflare";
|
||||||
import getPublicIp from "./getPublicIp";
|
import getPublicIp from "./getPublicIp";
|
||||||
import * as log from "./log";
|
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) {
|
if (ZONE_ID === undefined) {
|
||||||
log.error("could not access environment variable 'ZONE_ID'");
|
log.error("could not access environment variable 'ZONE_ID'");
|
||||||
}
|
}
|
||||||
if (DOMAIN_NAME === undefined) {
|
if (DOMAIN_NAMES === undefined) {
|
||||||
log.error("could not access environment variable 'DOMAIN_NAME'");
|
log.error("could not access environment variable 'DOMAIN_NAMES'");
|
||||||
}
|
}
|
||||||
if (API_KEY === undefined) {
|
if (API_KEY === undefined) {
|
||||||
log.error("could not access environment variable 'API_KEY'");
|
log.error("could not access environment variable 'API_KEY'");
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
ZONE_ID === undefined || DOMAIN_NAME === undefined || API_KEY === undefined
|
ZONE_ID === undefined || DOMAIN_NAMES === undefined || API_KEY === undefined
|
||||||
) {
|
) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dynamicDns = async () => {
|
const dynamicDns = async () => {
|
||||||
|
const domainNames = DOMAIN_NAMES.split(",");
|
||||||
try {
|
try {
|
||||||
const [publicIp, dnsRecord] = await Promise.all([
|
const [publicIp, dnsRecords] = await Promise.all([
|
||||||
getPublicIp(),
|
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(`public ip address remained at '${publicIp}', no patch needed`);
|
||||||
log.info(`checking again in ${INTERVAL} minutes\n`);
|
log.info(`checking again in ${INTERVAL} minutes\n`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(
|
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,
|
ZONE_ID,
|
||||||
dnsRecord.id,
|
|
||||||
API_KEY,
|
API_KEY,
|
||||||
publicIp,
|
publicIp,
|
||||||
DOMAIN_NAME,
|
|
||||||
"A",
|
"A",
|
||||||
);
|
);
|
||||||
log.info("patched dns entry");
|
log.info("patched dns entries");
|
||||||
log.info(`checking again in ${INTERVAL} minutes\n`);
|
log.info(`checking again in ${INTERVAL} minutes\n`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error((error as Error).message);
|
log.error((error as Error).message);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const STYLES = {
|
|||||||
ERROR: "\x1b[31m",
|
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)) {
|
if (!["DEBUG", "INFO", "WARN", "ERROR"].includes(LOG_LEVEL)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|||||||
Reference in New Issue
Block a user