@aws-amplify/cli-internal
Version:
Amplify CLI
117 lines • 5.93 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AmplifyDriftDetector = exports.run = void 0;
const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core");
const amplify_prompts_1 = require("@aws-amplify/amplify-prompts");
const chalk_1 = __importDefault(require("chalk"));
const detect_stack_drift_1 = require("./drift/detect-stack-drift");
const detect_local_drift_1 = require("./drift/detect-local-drift");
const detect_template_drift_1 = require("./drift/detect-template-drift");
const services_1 = require("./drift/services");
const spinning_logger_1 = require("./gen2-migration/_common/spinning-logger");
const run = async (context) => {
const logger = new spinning_logger_1.SpinningLogger('drift');
const detector = new AmplifyDriftDetector(context, logger);
logger.start('Drift detection');
const result = await detector.detect();
logger.succeed('Drift detection');
if (result.report) {
amplify_prompts_1.printer.info(result.report);
amplify_prompts_1.printer.info(chalk_1.default.yellow('Drift detected'));
}
else {
amplify_prompts_1.printer.info(chalk_1.default.green('No drift detected'));
}
if (result.code !== 0) {
process.exitCode = result.code;
}
};
exports.run = run;
class AmplifyDriftDetector {
constructor(context, logger) {
this.context = context;
this.logger = logger;
this.cfnService = new services_1.CloudFormationService(this.logger);
this.configService = new services_1.AmplifyConfigService();
}
async detect() {
this.configService.validateAmplifyProject();
this.logger.debug('Amplify project validated');
this.context.amplify.constructExeInfo(this.context);
const stackName = this.configService.getRootStackName();
this.logger.debug(`Root Stack: ${stackName}`);
const cfn = await this.cfnService.getClient(this.context);
this.logger.debug('CloudFormation client initialized');
if (!(await this.cfnService.validateStackExists(cfn, stackName))) {
throw new amplify_cli_core_1.AmplifyError('StackNotFoundError', {
message: `Stack ${stackName} does not exist.`,
resolution: 'Has the project been deployed? Run "amplify push" to deploy your project.',
});
}
let phase1Results;
let phase2Results;
let phase3Results;
this.logger.debug('Syncing cloud backend');
const syncSuccess = await this.cfnService.syncCloudBackendFromS3(this.context);
try {
this.logger.push('CloudFormation drift');
phase1Results = await (0, detect_stack_drift_1.detectStackDriftRecursive)(cfn, stackName, this.logger);
this.logger.pop();
this.logger.debug('Phase 1 complete');
if (!syncSuccess) {
phase2Results = {
changes: [],
skipped: true,
skipReason: 'S3 backend sync failed - cannot compare templates',
};
phase3Results = {
skipped: true,
skipReason: 'S3 backend sync failed - cannot compare local vs cloud',
};
this.logger.warn(chalk_1.default.yellow('Cloud backend sync failed - template drift and local drift will be skipped'));
}
else {
this.logger.debug('S3 sync completed successfully');
this.logger.push('Template changes');
this.logger.debug('Checking for template drift using changesets...');
phase2Results = await (0, detect_template_drift_1.detectTemplateDrift)(stackName, this.logger, cfn);
this.logger.pop();
this.logger.debug(`Phase 2 complete: ${phase2Results.changes.length} changes`);
this.logger.push('Local changes');
this.logger.debug('Checking local files vs cloud backend...');
phase3Results = await (0, detect_local_drift_1.detectLocalDrift)(this.context);
this.logger.pop();
this.logger.debug('Phase 3 complete');
}
}
catch (error) {
this.logger.pop();
throw error;
}
const driftReport = (0, services_1.createUnifiedCategoryView)(phase1Results, phase2Results, phase3Results);
const hasAnyErrors = phase1Results.incomplete || phase2Results.skipped || phase3Results.skipped;
if (hasAnyErrors) {
this.logger.warn(chalk_1.default.yellow('Drift detection encountered errors, results may be incomplete:'));
if (phase1Results.incomplete) {
this.logger.warn(chalk_1.default.yellow(`CloudFormation drift check incomplete - ${phase1Results.skippedStacks.length} nested stack(s) skipped`));
for (const skippedStack of phase1Results.skippedStacks) {
this.logger.debug(` - ${skippedStack}`);
}
}
if (phase2Results.skipped) {
this.logger.warn(chalk_1.default.yellow(`Template drift error: ${phase2Results.skipReason}`));
}
if (phase3Results.skipped) {
this.logger.warn(chalk_1.default.yellow(`Local drift error: ${phase3Results.skipReason}`));
}
this.logger.debug('Exit code 1: Incomplete drift detection - cannot guarantee no drift');
return { code: 1, report: driftReport !== null && driftReport !== void 0 ? driftReport : undefined };
}
return { code: driftReport ? 1 : 0, report: driftReport };
}
}
exports.AmplifyDriftDetector = AmplifyDriftDetector;
//# sourceMappingURL=drift.js.map