Commit 986e6e82 authored by nanahira's avatar nanahira

rewrite

parent 2a14faa6
Pipeline #327 passed with stages
in 5 minutes and 57 seconds
...@@ -53,92 +53,108 @@ interface DomainRecordInfo { ...@@ -53,92 +53,108 @@ interface DomainRecordInfo {
} }
let config: Config; let config: Config;
let client: Aliyun;
let cdnRecordsRegex: RegExp[];
const requestOption = { const requestOption = {
method: "POST" method: "POST"
} }
async function getRecords(): Promise<DomainRecordInfo[]> { class Checker {
console.log(`Fetching domain records of ${config.domain}.`) config: Config;
const res: DomainRecordInfo[] = []; client: Aliyun;
for (let i = 1; ; ++i) { cdnRecordsRegex: RegExp[];
const ret: DomainRecordReturnResult = await client.request("DescribeDomainRecords", { static order: number = 0;
DomainName: config.domain, id: number;
PageNumber: i, constructor(config: Config) {
PageSize: 500, this.config = config;
}, requestOption); this.client = new Aliyun(config.aliyun);
console.log(ret.TotalCount); this.cdnRecordsRegex = config.cdnRecords.map(m => new RegExp(m.match));
if (!ret.DomainRecords.Record.length) { this.id = ++Checker.order;
break; }
private message(msg: string) {
console.log(`${this.id} => ${msg}`);
}
async getRecords(): Promise<DomainRecordInfo[]> {
console.log(`Fetching domain records of ${config.domain}.`)
const res: DomainRecordInfo[] = [];
for (let i = 1; ; ++i) {
const ret: DomainRecordReturnResult = await this.client.request("DescribeDomainRecords", {
DomainName: config.domain,
PageNumber: i,
PageSize: 500,
}, requestOption);
console.log(ret.TotalCount);
if (!ret.DomainRecords.Record.length) {
break;
}
for (let record of ret.DomainRecords.Record.filter(m => {
return m.RR && m.Type === "CNAME" && _.any(this.cdnRecordsRegex, r => !!m.RR.match(r)) && _.every(this.cdnRecordsRegex, r => {
if (!m.Value.endsWith(config.domain)) {
return true;
}
const valuePrefix = m.Value.slice(0, m.Value.length - 1 - config.domain.length);
return !valuePrefix.match(r);
});
})) {
const port = _.find(config.cdnRecords, r => record.RR.match(r.match)).port;
console.log(`Found record ${record.RR}.${config.domain} => ${record.Value}:${port}.`);
res.push({record, port});
}
} }
for (let record of ret.DomainRecords.Record.filter(m => { return res;
return m.RR && m.Type === "CNAME" && _.any(cdnRecordsRegex, r => !!m.RR.match(r)) && _.every(cdnRecordsRegex, r => { }
if (!m.Value.endsWith(config.domain)) { async checkNode(address: string, port: number): Promise<boolean> {
return true; let currentTestDomain: string;
for (let i = 1; i <= this.config.retryCount; ++i) {
try {
for (let testDomain of this.config.testDomains) {
currentTestDomain = testDomain;
await axios.get(`https://${address}:${port}`, {
headers: {
Host: testDomain
},
timeout: this.config.timeout,
validateStatus: status => status < 500
});
} }
const valuePrefix = m.Value.slice(0, m.Value.length - 1 - config.domain.length); this.message(`Node ${address}:${port} is good.`);
return !valuePrefix.match(r); return true;
}); } catch (e) {
})) { this.message(`Node ${address}:${port} Failed in checking ${currentTestDomain} ${i}: ${e.toString()}`);
const port = _.find(config.cdnRecords, r => record.RR.match(r.match)).port; }
console.log(`Found record ${record.RR}.${config.domain} => ${record.Value}:${port}.`);
res.push({record, port});
} }
console.log(`Node ${address}:${port} is bad.`);
return false;
} }
return res; async checkRecord(recordInfo: DomainRecordInfo) {
} const record = recordInfo.record;
this.message(`${this.id} => Checking record ${record.RR}.${this.config.domain} ${record.Value}:${recordInfo.port} with old status of ${record.Status}.`)
async function checkNode(address: string, port: number): Promise<boolean> { const status = record.Status;
let currentTestDomain: string; const targetStatus = (await this.checkNode(record.Value, recordInfo.port)) ? "ENABLE" : "DISABLE";
for (let i = 1; i <= config.retryCount; ++i) { if (status != targetStatus) {
try { this.message(`Changing record status of ${record.RR}.${this.config.domain} ${record.Value}:${recordInfo.port} from ${status} to ${targetStatus}.`);
for (let testDomain of config.testDomains) { await this.client.request("SetDomainRecordStatus", {
currentTestDomain = testDomain; RecordId: record.RecordId,
await axios.get(`https://${address}:${port}`, { Status: targetStatus
headers: { }, requestOption);
Host: testDomain
},
timeout: config.timeout,
validateStatus: status => status < 500
});
}
console.log(`Node ${address}:${port} is good.`);
return true;
} catch (e) {
console.log(`Node ${address}:${port} Failed in checking ${currentTestDomain} ${i}: ${e.toString()}`);
} }
} }
console.log(`Node ${address}:${port} is bad.`); async start() {
return false; this.message(`Started.`);
} const records = await this.getRecords();
await Promise.all(records.map(r => {
async function checkRecord(recordInfo: DomainRecordInfo) { return this.checkRecord(r);
const record = recordInfo.record; }));
console.log(`Checking record ${record.RR}.${config.domain} ${record.Value}:${recordInfo.port} with old status of ${record.Status}.`) this.message(`Finished.`);
const status = record.Status;
const targetStatus = (await checkNode(record.Value, recordInfo.port)) ? "ENABLE" : "DISABLE";
if (status != targetStatus) {
console.log(`Changing record status of ${record.RR}.${config.domain} ${record.Value}:${recordInfo.port} from ${status} to ${targetStatus}.`);
await client.request("SetDomainRecordStatus", {
RecordId: record.RecordId,
Status: targetStatus
}, requestOption);
} }
} }
async function run() { async function run() {
console.log(`Started.`); const checker = new Checker(config);
const records = await getRecords(); await checker.start();
await Promise.all(records.map(checkRecord));
console.log(`Finished.`);
} }
async function main() { async function main() {
config = YAML.parse(await fs.promises.readFile("./config.yaml", "utf8")); config = YAML.parse(await fs.promises.readFile("./config.yaml", "utf8"));
client = new Aliyun(config.aliyun);
cdnRecordsRegex = config.cdnRecords.map(m => new RegExp(m.match));
//await run(); //await run();
(new CronJob(config.cronString, run, null, true, "Asia/Shanghai", null, true)).start(); (new CronJob(config.cronString, run, null, true, "Asia/Shanghai", null, true)).start();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment