Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove page rules #183

Merged
merged 24 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5a4ca1b
wip: domains2 - not using Page Rules
alunwcom Jul 2, 2024
f7320b5
wip: domain2 - initial functionality complete
alunwcom Jul 5, 2024
e8e6ead
working version of domains2
alunwcom Jul 5, 2024
f107731
Merge remote-tracking branch 'origin/main' into remove-page-rules
alunwcom Jul 12, 2024
8023298
Merge remote-tracking branch 'origin/main' into remove-page-rules
alunwcom Aug 9, 2024
28082f7
Merge remote-tracking branch 'origin' into remove-page-rules
alunwcom Oct 3, 2024
53adecf
Update worker to allow HTTPS_ONLY option
alunwcom Oct 4, 2024
fca76d8
replaced flat-cache with simple Map() in domain command
alunwcom Oct 4, 2024
54d411c
Disable eslint console warnings
alunwcom Oct 4, 2024
a585596
Reinstated answer confirmation
alunwcom Oct 4, 2024
aca6a75
Only load local files with .yaml extension
alunwcom Oct 4, 2024
5b1ed0b
wip - page rule migration
alunwcom Oct 4, 2024
9787d03
wip - page rule migration
alunwcom Oct 4, 2024
cc1bd94
wip - yaml check for page rule migration
alunwcom Oct 4, 2024
e0c63eb
Fixed issue in sync.js
alunwcom Oct 10, 2024
eb47f9b
Updated sync + added zone migration command
alunwcom Oct 22, 2024
b5150b3
Bumped version
alunwcom Oct 22, 2024
2fea655
Added getLocalYamlZone
alunwcom Oct 22, 2024
87aa2d3
Remove old domains command
alunwcom Oct 22, 2024
24380e2
Replaced the old domains command
alunwcom Oct 22, 2024
fbe137e
npm audit fix
alunwcom Nov 8, 2024
a2957d3
Capture migration code...
alunwcom Nov 19, 2024
f4d024d
Removed migration code
alunwcom Nov 19, 2024
d7b96e8
Removed migration code
alunwcom Nov 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
node_modules/
.cache-db/
.wrangler/
worker-local/
.vscode/
.env
wrangler.toml
*.log
Expand Down
2 changes: 2 additions & 0 deletions commands/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* @copyright 2020 John Wiley & Sons, Inc.
* @license MIT
*/

/* eslint no-console: "off" */
import * as fs from 'node:fs';
import * as path from 'node:path';
import chalk from 'chalk';
Expand Down
1 change: 1 addition & 0 deletions commands/compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @license MIT
*/

/* eslint no-console: "off" */
import * as fs from 'node:fs';
import * as path from 'node:path';
import chalk from 'chalk';
Expand Down
1 change: 1 addition & 0 deletions commands/dash.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint no-console: "off" */
import open from 'open';

/**
Expand Down
1 change: 1 addition & 0 deletions commands/describe.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint no-console: "off" */
import * as fs from 'node:fs';
import * as path from 'node:path';
import chalk from 'chalk';
Expand Down
1 change: 1 addition & 0 deletions commands/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @license MIT
*/

/* eslint no-console: "off" */
import chalk from 'chalk';
import SimpleTable from 'cli-simple-table';
import inquirer from 'inquirer';
Expand Down
262 changes: 262 additions & 0 deletions commands/domains2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
/**
* @copyright 2020 John Wiley & Sons, Inc.
* @license MIT
*/

/* eslint no-console: "off" */
import * as path from 'node:path';
import chalk from 'chalk';
import inquirer from 'inquirer';
import {
convertToIdValueObjectArray,
createDNSRecords,
getDefaultDnsRecords,
lightblue,
purple
} from '../lib/shared.js';
import {
getLocalYamlSettings,
getLocalYamlZones
} from '../lib/sync-shared.js';
import {
deleteDnsRecord,
deleteWorkerRouteById,
getAccountById,
getDnsRecordsByZoneId,
getWorkerRoutesByZoneId,
getZonesByAccount,
updateZoneSettingsById,
createWorkerRoute,
createZone,
putWorkerKVValuesByDomain
} from '../lib/cloudflare.js';

const cache = new Map(); // empty cache Map()
let localZoneSettings; // empty zone settings object

// util: add value to cache map without wiping existing data
const insertValue = (key, value) => {
const currentData = cache.get(key);
if (currentData) {
cache.set(key, { ...currentData, ...value });
} else {
cache.set(key, value);
}
return cache.get(key);
};

const outputCloudflareZoneDetails = (zones, configDir) => {
console.info(`${chalk.bold(zones.length)} Zones:`);
zones.forEach((zone) => {
let status_icon = chalk.green('✓ ');
if (zone.status !== 'active') status_icon = chalk.blue('🕓');
if (zone.paused) status_icon = chalk.blue('⏸️');

console.info(`${status_icon} ${chalk.bold(zone.name)} - ${chalk[zone.plan.name === 'Enterprise Website' ? 'red' : 'green'](zone.plan.name)}`);
if (zone.status === 'pending' && !zone.paused && zone.type !== 'partial') {
console.info(lightblue(`Update the nameservers to: ${zone.name_servers.join(', ')}`));
}
if (zone.status === 'pending' && !zone.paused && zone.type === 'partial') {
console.info(lightblue('CNAME Setup required. See Cloudflare UX.'));
}
// output a warning if there is no local description
const redir_filename = configDir.contents
.filter((f) => f.substr(0, zone.name.length) === zone.name)[0];
if (undefined === redir_filename) {
console.warn(purple(`No redirect description for ${chalk.bold(zone.name)} was found.`));
}
});
};

const addZoneToAccount = async (data, account, argv) => {
if (!data || !data.yaml || !data.yaml.zone || !data.yaml.yamlPath) {
// this should never happen
console.error('Invalid zone data! No data found for this zone: ', data);
return;
}
const { zone, yamlPath, description } = data.yaml;

if (!description || description === '') {
console.error(lightblue(`No YAML data found for ${zone} [${path.relative(process.cwd(), yamlPath)}], skipping!`));
return;
}

if (zone !== description.name) {
console.error(lightblue(`Zone name in YAML (${zone}) doesn't match file name [${path.relative(process.cwd(), yamlPath)}], skipping!`));
return;
}

// handle zone with no redirects (e.g. parked domain)
let redirects = [];
if (description.redirects && description.redirects.length > 0) {
redirects = description.redirects;
}

const answer = await inquirer.prompt({
Fixed Show fixed Hide fixed
type: 'confirm',
name: 'confirmCreate',
message: `Add ${zone} with ${redirects.length} ${redirects.length > 1 ? 'redirects' : 'redirect'} to ${account.name}?`,
default: false
});
if (!answer.confirmCreate) {
// Do nothing
return;
}

console.info('Creating the zone...');
// create zone
const response = await createZone(zone, account.id);
if (response.data.success) {
const { id, name, status } = response.data.result;
console.info(` ${chalk.bold(name)}${chalk.gray(' has been created and is ')}${lightblue(status)}`);

// update zone settings
const settingsResponse = await updateZoneSettingsById(id, {
items: convertToIdValueObjectArray(localZoneSettings)
});
if (settingsResponse.data.success) {
console.info(chalk.gray(' Updated security settings.'));
}

// check for any worker routes that may exist if
// the zone was previously deleted and re-added
const existingWorkerRoutes = await getWorkerRoutesByZoneId(id);
if (existingWorkerRoutes.length > 0) {
const deleteResources = await inquirer.prompt({
type: 'confirm',
name: 'confirmDelete',
message: chalk.yellow(`${zone} has existing worker routes! Delete these before continuing?`),
default: false
});
if (!deleteResources.confirmDelete) {
console.warn(lightblue('Exiting zone creation before complete! Check zone manually.'));
return;
}
const promises = existingWorkerRoutes.map((route) => deleteWorkerRouteById(id, route.id));
await Promise.allSettled(promises);
}

/* create worker route
* NOTE: sticking with worker routes over custom domains for now, to give
* option of flexibility for domains with 'passthrough' option.
*/
const workerName = argv.workerName ? argv.workerName : 'redir';
const workerResponse = await createWorkerRoute(id, name, workerName);
if (workerResponse.data.success) {
console.info(chalk.gray(' Worker Route configured successfully.'));
}
// add redirects to worker KV
const kvResponse = await putWorkerKVValuesByDomain(
account.id,
argv.workerKvNamespace,
name,
description
);
if (kvResponse.data.success) {
console.info(chalk.gray(' Redirect Description stored in Key Value storage successfully.'));
}

// check for any dns records that may exist if
// the zone was previously deleted and re-added
const existingDns = await getDnsRecordsByZoneId(id);
if (existingDns.length > 0) {
const deleteResources = await inquirer.prompt({
type: 'confirm',
name: 'confirmDelete',
message: chalk.yellow(`${zone} has existing DNS records! Delete these before continuing?`),
default: false
});
if (!deleteResources.confirmDelete) {
console.warn(lightblue('Exiting zone creation before complete! Check zone manually.'));
return;
}
const promises = existingDns.map((record) => deleteDnsRecord(id, record.id));
await Promise.allSettled(promises);
}

await createDNSRecords(id, getDefaultDnsRecords(zone));
}
};

/**
* Lists missing zones in Cloudflare, and creates them if desired.
*/
const command = ['domains2', 'zones2'];
const describe = 'List domains in the current Cloudflare account';
// const builder = (yargs) => {};

const handler = async (argv) => {
// load remote/cloudflare zones and add to cache
const cfZones = await getZonesByAccount(argv.accountId);
cfZones.map((data) => insertValue(data.name, { cloudflare: data }));

outputCloudflareZoneDetails(cfZones, argv.configDir);

// fetch list of all zones defined in yaml configuration
const yamlZones = await getLocalYamlZones(argv.configDir);
yamlZones.map((data) => insertValue(data.zone, { yaml: data }));

// load local config to cache (fail on error - e.g. missing params)
localZoneSettings = await getLocalYamlSettings(argv.configDir);

// get array of cache keys
const cacheKeys = Array.from(cache.keys());

// zones in cloudflare but not in yaml
const zone_but_no_description = cacheKeys.filter((key) => {
const zone = cache.get(key);
return zone.cloudflare && !zone.yaml;
});
if (zone_but_no_description.length > 0) {
console.info(`\nThe following ${chalk.bold(zone_but_no_description.length)} domains are not yet described locally:`);
zone_but_no_description.forEach((zone_name) => {
console.info(` - ${zone_name}`);
});
}

// zones in yaml but not in cloudflare
const described_but_no_zone = cacheKeys.filter((key) => {
const zone = cache.get(key);
return zone.yaml && !zone.cloudflare;
});
if (described_but_no_zone.length > 0) {
console.info(`\nThe following ${chalk.bold(described_but_no_zone.length)} domains are not yet in Cloudflare:`);
described_but_no_zone.forEach((zone_name) => {
const zone = cache.get(zone_name);
let yaml_name;
if (zone.yaml && zone.yaml.description) {
yaml_name = zone.yaml.description.name;
}
const yamlFilename = `${zone_name}.yaml`;
console.info(` - ${yaml_name} (see ${path.join(argv.configDir.name, yamlFilename)})`);
});

// ask if the user is ready to create the above missing zones
console.info();
const answer = await inquirer.prompt({
type: 'confirm',
name: 'confirmCreateIntent',
message: 'Are you ready to create the missing zones on Cloudflare?',
default: false
});
if (answer.confirmCreateIntent) {
const account = await getAccountById(argv.accountId);
console.info(`We'll be adding these to the '${account.name}' Cloudflare account.`);

/* eslint no-restricted-syntax: ["error"] */
for await (const zone_name of described_but_no_zone) {
try {
const zone = cache.get(zone_name);
await addZoneToAccount(zone, account, argv);
} catch (err) {
console.dir(err);
process.exit(1);
}
}
}
}
};

export {
command, describe, handler
};
Loading
Loading