#!/usr/bin/env node /** * This script reads the Azure website and updates our hard-coded file it needed */ const fs = require('fs'); const path = require('path'); const axios = require('axios'); console.log('Updating Azure regions in Availability Zones'); console.log('============================================'); console.log(''); const SCRIPT = process.argv[1]; const DIR = path.resolve(SCRIPT, '../../..'); const ENDPOINTS_URL = 'https://learn.microsoft.com/en-us/azure/reliability/regions-list'; const TS_FILE = path.resolve(DIR, 'pkg/aks/util/aks-regions.ts'); const COLUMN_REGEX = /(.*)<\/td>/; const US_GOV = 'usgov'; function findRegions(body) { const regions = []; let inTable = false; let inRow = false; let inColumn = false; let row = []; let column = '' body.split('\n').forEach((line) => { line = line.trim(); if (line.indexOf('= 0) { inTable = true; } else if (inTable) { if (line.indexOf('') >= 0) { inTable = false; } else if (inRow) { if (!inColumn && line.indexOf('') === 0) { inColumn = true; column = line; if (line.endsWith('')) { row.push(column); inColumn = false; } } else if (inColumn && line.endsWith('')) { column += line; row.push(column); inColumn = false; } else if (line.indexOf('') === 0) { inRow = false; if (row.length === 5) { if (!row[0].startsWith('')) { const m = row[0].match(COLUMN_REGEX); if (m && m.length === 2) { let region = m[1].toLowerCase(); region = region.replaceAll(' ', ''); regions.push(region); } } } } } else if (!inRow && line.indexOf('') == 0) { inRow = true; row = []; } } }); return regions.sort(); } function cleanItem(item) { const p = item.split(':'); if (p.length === 2) { return p[0]; } return undefined; } function readExisting() { const data = fs.readFileSync(TS_FILE).toString(); const items = []; let processing = false; let done = false; data.split(/\r?\n/).forEach(line => { line = line.trim(); if (!done) { if (!processing) { if (line.startsWith('export const ')) { processing = true; } } else { if (line === '} as any;') { processing = false; done = true; } else { const r = cleanItem(line); if (r) { items.push(r); } } } } }); return items.sort(); } function writeNewFile(regions) { let lines = ['export const regionsWithAvailabilityZones = {']; let maxLength = 1; regions.forEach((r) => { if (r.length > maxLength) { maxLength = r.length + 1; // Add room for : } }); regions.forEach((r) => { const key = `${r}:`.padEnd(maxLength); lines.push(` ${ key } true,`) }); lines.push('} as any;'); lines.push(''); fs.writeFileSync(TS_FILE, lines.join('\n')); } const existing = readExisting(); axios.get(ENDPOINTS_URL, { responseType: 'document' }).then((res) => { if (res.status !== 200 || !res.data) { console.error(`Could not fetch Azure data - status ${ res.statusCode } ${ res.statusMessage }`); process.exit(1); } const regions = findRegions(res.data); const govRegions = existing.filter((r) => r.startsWith(US_GOV)); const existingCount = existing.length; if (regions.length === 0) { console.error('Could not fetch data from Azure - no regions found'); process.exit(2); } console.log(`Existing regions in our codebase: ${ existingCount - govRegions.length } (Excluding US Government regions)`); console.log(existing); console.log(''); console.log(`Regions from Azure: ${ regions.length }`); console.log(regions); console.log(''); const removed = []; existing.forEach((r) => { if (r.startsWith(US_GOV)) { regions.push(r); } else if (!regions.includes(r)) { removed.push(r); } }); console.log(''); console.log(`US Government regions to be retained: ${ govRegions.join(', ') }`); console.log(''); if (removed.length) { console.log(`These region(s) have been removed: ${ removed.join(', ') }`); } const added = []; regions.forEach((r) => { if (!existing.includes(r)) { added.push(r); } }); if (added.length) { console.log(`These region(s) have been added: ${ added.join(', ') }`); } if (added.length || removed.length) { // Sort the regions (needs a resort if we added back in usgov regions) writeNewFile(regions.sort()); console.log(''); console.log(`Regions updated from ${ existingCount } to ${ regions.length }`); console.log(''); } else { console.log('No changes to the Azure region data'); } });