mirror of
https://github.com/elmerfds/TrafegoDNS.git
synced 2026-01-13 22:59:39 -06:00
335 lines
12 KiB
Bash
335 lines
12 KiB
Bash
#!/bin/sh
|
|
# Setup script for TrafegoDNS CLI
|
|
set -e
|
|
|
|
# Create bin directory if it doesn't exist
|
|
mkdir -p /app/bin
|
|
|
|
# Create CLI entry script
|
|
cat > /app/bin/trafego << 'EOF'
|
|
#!/usr/bin/env node
|
|
|
|
/**
|
|
* TrafegoDNS CLI tool
|
|
* Provides command-line interface for interacting with TrafegoDNS
|
|
*/
|
|
const { program } = require('commander');
|
|
const chalk = require('chalk');
|
|
const pkg = require('../package.json');
|
|
|
|
// Set up CLI context
|
|
const context = {};
|
|
|
|
// Check if we can access the application state and services
|
|
try {
|
|
// Try to access global objects (works when run within the application)
|
|
if (global.actionBroker) {
|
|
context.actionBroker = global.actionBroker;
|
|
context.stateStore = global.stateStore;
|
|
context.apiClient = global.apiClient;
|
|
} else {
|
|
// We're running as a standalone CLI
|
|
// Initialize ApiClient if needed
|
|
const ApiClient = require('../src/cli/apiClient');
|
|
const config = {
|
|
localAuthBypass: {
|
|
cliToken: process.env.CLI_TOKEN || 'trafegodns-cli'
|
|
}
|
|
};
|
|
context.apiClient = new ApiClient(config);
|
|
}
|
|
} catch (error) {
|
|
// Continue without context - commands will handle missing context
|
|
console.warn(chalk.yellow('Warning: Running in standalone mode, some features may be limited'));
|
|
}
|
|
|
|
// Create DNS commands
|
|
const dnsCommands = {
|
|
refreshRecords: async (args, ctx) => {
|
|
try {
|
|
console.log(chalk.yellow('Refreshing DNS records...'));
|
|
|
|
// Try API client first
|
|
if (ctx.apiClient) {
|
|
await ctx.apiClient.refreshDns();
|
|
}
|
|
// Then try action broker
|
|
else if (ctx.actionBroker) {
|
|
await ctx.actionBroker.dispatch({
|
|
type: 'DNS_REFRESH',
|
|
metadata: { source: 'cli' }
|
|
});
|
|
}
|
|
// Last resort - try direct access
|
|
else if (global.services && global.services.DNSManager) {
|
|
await global.services.DNSManager.refreshRecords();
|
|
}
|
|
else {
|
|
console.log(chalk.red('No method available to refresh DNS records'));
|
|
return;
|
|
}
|
|
|
|
console.log(chalk.green('DNS records refreshed successfully'));
|
|
} catch (error) {
|
|
console.error(chalk.red(`Error refreshing DNS records: ${error.message}`));
|
|
}
|
|
},
|
|
|
|
processRecords: async (args, ctx) => {
|
|
try {
|
|
const forceUpdate = args.force || false;
|
|
|
|
console.log(chalk.yellow(`Processing DNS records${forceUpdate ? ' (forced)' : ''}...`));
|
|
|
|
// Use API if available
|
|
if (ctx.apiClient) {
|
|
try {
|
|
// Try to use processDnsRecords method
|
|
if (ctx.apiClient.processDnsRecords) {
|
|
const response = await ctx.apiClient.processDnsRecords(forceUpdate);
|
|
|
|
if (response.status === 'success') {
|
|
console.log(chalk.green('DNS records processed successfully'));
|
|
console.log(`\nSummary:`);
|
|
console.log(`- Created: ${response.data.created || 0} records`);
|
|
console.log(`- Updated: ${response.data.updated || 0} records`);
|
|
console.log(`- Deleted: ${response.data.deleted || 0} records`);
|
|
console.log(`- Orphaned: ${response.data.orphaned || 0} records`);
|
|
console.log(`- Total: ${response.data.total || 0} records processed`);
|
|
} else {
|
|
console.warn(chalk.yellow('DNS processing returned an unexpected response'));
|
|
}
|
|
return;
|
|
}
|
|
} catch (apiError) {
|
|
console.warn(chalk.yellow(`API method failed: ${apiError.message}`));
|
|
}
|
|
}
|
|
|
|
// Direct method using globals
|
|
try {
|
|
if (global.services && global.services.Monitor) {
|
|
const monitor = global.services.Monitor;
|
|
|
|
console.log('Processing via direct service access...');
|
|
|
|
// Force a poll of Traefik if it's a Traefik monitor
|
|
if (monitor.pollTraefik && typeof monitor.pollTraefik === 'function') {
|
|
await monitor.pollTraefik(true);
|
|
console.log(chalk.green('Traefik routes polled successfully'));
|
|
}
|
|
|
|
// Process hostnames if available
|
|
if (monitor.processHostnames && typeof monitor.processHostnames === 'function') {
|
|
const result = await monitor.processHostnames(forceUpdate);
|
|
console.log(chalk.green('Hostnames processed successfully'));
|
|
|
|
// Display results if available
|
|
if (result && typeof result === 'object') {
|
|
console.log(`\nSummary:`);
|
|
console.log(`- Created: ${result.created || 0} records`);
|
|
console.log(`- Updated: ${result.updated || 0} records`);
|
|
console.log(`- Orphaned: ${result.orphaned || 0} records`);
|
|
console.log(`- Total: ${result.total || 0} hostnames processed`);
|
|
}
|
|
} else {
|
|
console.warn(chalk.yellow('Direct hostname processing not available'));
|
|
}
|
|
|
|
return;
|
|
}
|
|
} catch (directError) {
|
|
console.warn(chalk.yellow(`Direct service access failed: ${directError.message}`));
|
|
}
|
|
|
|
// If we got here, no method worked
|
|
console.error(chalk.red('Cannot process DNS records: No valid method available'));
|
|
} catch (error) {
|
|
console.error(chalk.red(`Error processing DNS records: ${error.message}`));
|
|
}
|
|
}
|
|
};
|
|
|
|
// Create DB commands
|
|
const dbCommands = {
|
|
listRecords: async (args, ctx) => {
|
|
try {
|
|
console.log(chalk.yellow('Listing DNS records...'));
|
|
|
|
// Try API client first
|
|
if (ctx.apiClient && ctx.apiClient.getDnsRecords) {
|
|
const response = await ctx.apiClient.getDnsRecords();
|
|
if (response.data && Array.isArray(response.data)) {
|
|
console.log(`Found ${response.data.length} DNS records`);
|
|
response.data.forEach(record => {
|
|
const id = record.id || record.record_id;
|
|
const status = record.orphaned ? 'Orphaned' : (record.managed ? 'Managed' : 'Unmanaged');
|
|
console.log(`${id.substr(0, 8)}... | ${record.type.padEnd(6)} | ${record.name.padEnd(30)} | ${status}`);
|
|
});
|
|
} else {
|
|
console.log('No DNS records found or unexpected response format');
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Try direct access to global state
|
|
if (global.stateStore) {
|
|
const records = global.stateStore.getState('dns.records') || [];
|
|
console.log(`Found ${records.length} DNS records`);
|
|
records.forEach(record => {
|
|
const id = record.id || record.record_id;
|
|
const status = record.orphaned ? 'Orphaned' : (record.managed ? 'Managed' : 'Unmanaged');
|
|
console.log(`${id.substr(0, 8)}... | ${record.type.padEnd(6)} | ${record.name.padEnd(30)} | ${status}`);
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Last resort - try direct database access
|
|
if (global.services && global.services.DNSManager) {
|
|
const records = await global.services.DNSManager.dnsProvider.getRecordsFromCache(true) || [];
|
|
console.log(`Found ${records.length} DNS records`);
|
|
records.forEach(record => {
|
|
const id = record.id || record.record_id;
|
|
const status = global.services.DNSManager.recordTracker.isRecordOrphaned(record) ? 'Orphaned' :
|
|
(global.services.DNSManager.recordTracker.isTracked(record) ? 'Managed' : 'Unmanaged');
|
|
console.log(`${id.substr(0, 8)}... | ${record.type.padEnd(6)} | ${record.name.padEnd(30)} | ${status}`);
|
|
});
|
|
return;
|
|
}
|
|
|
|
console.log(chalk.red('No method available to list DNS records'));
|
|
} catch (error) {
|
|
console.error(chalk.red(`Error listing DNS records: ${error.message}`));
|
|
}
|
|
},
|
|
|
|
status: async (args, ctx) => {
|
|
try {
|
|
console.log(chalk.yellow('Checking database status...'));
|
|
|
|
// Try direct access to global database object
|
|
if (global.services && global.services.DNSManager) {
|
|
console.log('DNS provider: ' + (global.services.DNSManager.config.dnsProvider || 'unknown'));
|
|
console.log('Domain: ' + (global.services.DNSManager.config.getProviderDomain() || 'unknown'));
|
|
if (global.stateStore) {
|
|
const records = global.stateStore.getState('dns.records') || [];
|
|
console.log(`Records: ${records.length}`);
|
|
}
|
|
return;
|
|
}
|
|
|
|
console.log(chalk.red('No method available to check database status'));
|
|
} catch (error) {
|
|
console.error(chalk.red(`Error checking database status: ${error.message}`));
|
|
}
|
|
},
|
|
|
|
cleanup: async (args, ctx) => {
|
|
try {
|
|
console.log(chalk.yellow('Cleaning up orphaned records...'));
|
|
|
|
// Try API client first
|
|
if (ctx.apiClient && ctx.apiClient.runCleanup) {
|
|
await ctx.apiClient.runCleanup();
|
|
console.log(chalk.green('Cleanup completed'));
|
|
return;
|
|
}
|
|
|
|
// Try action broker if available
|
|
if (ctx.actionBroker) {
|
|
await ctx.actionBroker.dispatch({
|
|
type: 'DNS_ORPHANED_CLEANUP',
|
|
metadata: { source: 'cli', forceImmediate: true }
|
|
});
|
|
console.log(chalk.green('Cleanup completed'));
|
|
return;
|
|
}
|
|
|
|
// Last resort - try direct access
|
|
if (global.services && global.services.DNSManager && global.services.DNSManager.cleanupOrphanedRecords) {
|
|
await global.services.DNSManager.cleanupOrphanedRecords([]);
|
|
console.log(chalk.green('Cleanup completed'));
|
|
return;
|
|
}
|
|
|
|
console.log(chalk.red('No method available to cleanup orphaned records'));
|
|
} catch (error) {
|
|
console.error(chalk.red(`Error cleaning up orphaned records: ${error.message}`));
|
|
}
|
|
}
|
|
};
|
|
|
|
// Set up CLI program
|
|
program
|
|
.name('trafego')
|
|
.description('TrafegoDNS CLI tool')
|
|
.version(pkg?.version || '1.11.0');
|
|
|
|
// DNS commands
|
|
program
|
|
.command('dns')
|
|
.description('DNS management commands')
|
|
.addCommand(
|
|
program.createCommand('refresh')
|
|
.description('Refresh DNS records from provider')
|
|
.action(args => dnsCommands.refreshRecords(args, context))
|
|
)
|
|
.addCommand(
|
|
program.createCommand('process')
|
|
.description('Process hostnames and update DNS records')
|
|
.option('-f, --force', 'Force update of all DNS records')
|
|
.action(args => dnsCommands.processRecords(args, context))
|
|
);
|
|
|
|
// Database commands
|
|
program
|
|
.command('db')
|
|
.description('Database management commands')
|
|
.addCommand(
|
|
program.createCommand('records')
|
|
.description('List DNS records')
|
|
.action(args => dbCommands.listRecords(args, context))
|
|
)
|
|
.addCommand(
|
|
program.createCommand('status')
|
|
.description('Show database status')
|
|
.action(args => dbCommands.status(args, context))
|
|
)
|
|
.addCommand(
|
|
program.createCommand('cleanup')
|
|
.description('Clean up orphaned records')
|
|
.action(args => dbCommands.cleanup(args, context))
|
|
);
|
|
|
|
// Handle unknown commands
|
|
program.on('command:*', () => {
|
|
console.error(chalk.red(`Invalid command: ${program.args.join(' ')}`));
|
|
console.error('See --help for a list of available commands.');
|
|
process.exit(1);
|
|
});
|
|
|
|
// Parse command line arguments
|
|
program.parse(process.argv);
|
|
|
|
// Show help if no arguments provided
|
|
if (!process.argv.slice(2).length) {
|
|
program.outputHelp();
|
|
}
|
|
EOF
|
|
|
|
# Make script executable
|
|
chmod +x /app/bin/trafego
|
|
|
|
# Create CLI wrapper in /usr/local/bin for system-wide access
|
|
cat > /usr/local/bin/trafego << 'EOF'
|
|
#!/bin/sh
|
|
exec node /app/bin/trafego "$@"
|
|
EOF
|
|
|
|
chmod +x /usr/local/bin/trafego
|
|
|
|
# Install required dependencies if not already installed
|
|
cd /app
|
|
npm install --no-save commander@11.1.0 chalk@4.1.2
|
|
|
|
echo "TrafegoDNS CLI setup complete! You can now use 'trafego' command." |