@friggframework/devtools 2.0.0-next.45 → 2.0.0-next.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/infrastructure/ARCHITECTURE.md +487 -0
- package/infrastructure/HEALTH.md +468 -0
- package/infrastructure/README.md +51 -0
- package/infrastructure/__tests__/postgres-config.test.js +914 -0
- package/infrastructure/__tests__/template-generation.test.js +687 -0
- package/infrastructure/create-frigg-infrastructure.js +1 -1
- package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
- package/infrastructure/{DEPLOYMENT-INSTRUCTIONS.md → docs/deployment-instructions.md} +3 -3
- package/infrastructure/{IAM-POLICY-TEMPLATES.md → docs/iam-policy-templates.md} +9 -10
- package/infrastructure/domains/database/aurora-builder.js +809 -0
- package/infrastructure/domains/database/aurora-builder.test.js +950 -0
- package/infrastructure/domains/database/aurora-discovery.js +87 -0
- package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
- package/infrastructure/domains/database/aurora-resolver.js +210 -0
- package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
- package/infrastructure/domains/database/migration-builder.js +633 -0
- package/infrastructure/domains/database/migration-builder.test.js +294 -0
- package/infrastructure/domains/database/migration-resolver.js +163 -0
- package/infrastructure/domains/database/migration-resolver.test.js +337 -0
- package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
- package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
- package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
- package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
- package/infrastructure/domains/health/application/ports/index.js +26 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
- package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
- package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
- package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
- package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
- package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
- package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
- package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
- package/infrastructure/domains/health/domain/entities/issue.js +299 -0
- package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
- package/infrastructure/domains/health/domain/entities/resource.js +159 -0
- package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
- package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
- package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
- package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
- package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
- package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
- package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
- package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
- package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
- package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
- package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
- package/infrastructure/domains/integration/integration-builder.js +397 -0
- package/infrastructure/domains/integration/integration-builder.test.js +593 -0
- package/infrastructure/domains/integration/integration-resolver.js +170 -0
- package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
- package/infrastructure/domains/integration/websocket-builder.js +69 -0
- package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
- package/infrastructure/domains/networking/vpc-builder.js +1829 -0
- package/infrastructure/domains/networking/vpc-builder.test.js +1262 -0
- package/infrastructure/domains/networking/vpc-discovery.js +177 -0
- package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
- package/infrastructure/domains/networking/vpc-resolver.js +324 -0
- package/infrastructure/domains/networking/vpc-resolver.test.js +501 -0
- package/infrastructure/domains/parameters/ssm-builder.js +79 -0
- package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
- package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
- package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
- package/infrastructure/{iam-generator.js → domains/security/iam-generator.js} +2 -2
- package/infrastructure/domains/security/kms-builder.js +366 -0
- package/infrastructure/domains/security/kms-builder.test.js +374 -0
- package/infrastructure/domains/security/kms-discovery.js +80 -0
- package/infrastructure/domains/security/kms-discovery.test.js +177 -0
- package/infrastructure/domains/security/kms-resolver.js +96 -0
- package/infrastructure/domains/security/kms-resolver.test.js +216 -0
- package/infrastructure/domains/shared/base-builder.js +112 -0
- package/infrastructure/domains/shared/base-resolver.js +186 -0
- package/infrastructure/domains/shared/base-resolver.test.js +305 -0
- package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
- package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
- package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
- package/infrastructure/domains/shared/cloudformation-discovery.js +375 -0
- package/infrastructure/domains/shared/cloudformation-discovery.test.js +590 -0
- package/infrastructure/domains/shared/environment-builder.js +119 -0
- package/infrastructure/domains/shared/environment-builder.test.js +247 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.js +544 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +377 -0
- package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
- package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
- package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
- package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
- package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
- package/infrastructure/domains/shared/resource-discovery.js +192 -0
- package/infrastructure/domains/shared/resource-discovery.test.js +552 -0
- package/infrastructure/domains/shared/types/app-definition.js +205 -0
- package/infrastructure/domains/shared/types/discovery-result.js +106 -0
- package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
- package/infrastructure/domains/shared/types/index.js +46 -0
- package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
- package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +380 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +248 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +55 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +138 -0
- package/infrastructure/{env-validator.js → domains/shared/validation/env-validator.js} +2 -1
- package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
- package/infrastructure/esbuild.config.js +53 -0
- package/infrastructure/infrastructure-composer.js +87 -0
- package/infrastructure/{serverless-template.test.js → infrastructure-composer.test.js} +115 -24
- package/infrastructure/scripts/build-prisma-layer.js +553 -0
- package/infrastructure/scripts/build-prisma-layer.test.js +102 -0
- package/infrastructure/{build-time-discovery.js → scripts/build-time-discovery.js} +80 -48
- package/infrastructure/{build-time-discovery.test.js → scripts/build-time-discovery.test.js} +5 -4
- package/layers/prisma/nodejs/package.json +8 -0
- package/management-ui/server/utils/cliIntegration.js +1 -1
- package/management-ui/server/utils/environment/awsParameterStore.js +29 -18
- package/package.json +11 -11
- package/frigg-cli/.eslintrc.js +0 -141
- package/frigg-cli/__tests__/unit/commands/build.test.js +0 -251
- package/frigg-cli/__tests__/unit/commands/db-setup.test.js +0 -548
- package/frigg-cli/__tests__/unit/commands/install.test.js +0 -400
- package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -346
- package/frigg-cli/__tests__/unit/utils/database-validator.test.js +0 -366
- package/frigg-cli/__tests__/unit/utils/error-messages.test.js +0 -304
- package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +0 -486
- package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
- package/frigg-cli/__tests__/utils/prisma-mock.js +0 -194
- package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
- package/frigg-cli/__tests__/utils/test-setup.js +0 -287
- package/frigg-cli/build-command/index.js +0 -65
- package/frigg-cli/db-setup-command/index.js +0 -193
- package/frigg-cli/deploy-command/index.js +0 -175
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -301
- package/frigg-cli/generate-command/azure-generator.js +0 -43
- package/frigg-cli/generate-command/gcp-generator.js +0 -47
- package/frigg-cli/generate-command/index.js +0 -332
- package/frigg-cli/generate-command/terraform-generator.js +0 -555
- package/frigg-cli/generate-iam-command.js +0 -118
- package/frigg-cli/index.js +0 -75
- package/frigg-cli/index.test.js +0 -158
- package/frigg-cli/init-command/backend-first-handler.js +0 -756
- package/frigg-cli/init-command/index.js +0 -93
- package/frigg-cli/init-command/template-handler.js +0 -143
- package/frigg-cli/install-command/backend-js.js +0 -33
- package/frigg-cli/install-command/commit-changes.js +0 -16
- package/frigg-cli/install-command/environment-variables.js +0 -127
- package/frigg-cli/install-command/environment-variables.test.js +0 -136
- package/frigg-cli/install-command/index.js +0 -54
- package/frigg-cli/install-command/install-package.js +0 -13
- package/frigg-cli/install-command/integration-file.js +0 -30
- package/frigg-cli/install-command/logger.js +0 -12
- package/frigg-cli/install-command/template.js +0 -90
- package/frigg-cli/install-command/validate-package.js +0 -75
- package/frigg-cli/jest.config.js +0 -124
- package/frigg-cli/package.json +0 -54
- package/frigg-cli/start-command/index.js +0 -149
- package/frigg-cli/start-command/start-command.test.js +0 -297
- package/frigg-cli/test/init-command.test.js +0 -180
- package/frigg-cli/test/npm-registry.test.js +0 -319
- package/frigg-cli/ui-command/index.js +0 -154
- package/frigg-cli/utils/app-resolver.js +0 -319
- package/frigg-cli/utils/backend-path.js +0 -25
- package/frigg-cli/utils/database-validator.js +0 -161
- package/frigg-cli/utils/error-messages.js +0 -257
- package/frigg-cli/utils/npm-registry.js +0 -167
- package/frigg-cli/utils/prisma-runner.js +0 -280
- package/frigg-cli/utils/process-manager.js +0 -199
- package/frigg-cli/utils/repo-detection.js +0 -405
- package/infrastructure/aws-discovery.js +0 -1176
- package/infrastructure/aws-discovery.test.js +0 -1220
- package/infrastructure/serverless-template.js +0 -2094
- /package/infrastructure/{WEBSOCKET-CONFIGURATION.md → docs/WEBSOCKET-CONFIGURATION.md} +0 -0
- /package/infrastructure/{GENERATE-IAM-DOCS.md → docs/generate-iam-command.md} +0 -0
- /package/infrastructure/{iam-generator.test.js → domains/security/iam-generator.test.js} +0 -0
- /package/infrastructure/{frigg-deployment-iam-stack.yaml → domains/security/templates/frigg-deployment-iam-stack.yaml} +0 -0
- /package/infrastructure/{iam-policy-basic.json → domains/security/templates/iam-policy-basic.json} +0 -0
- /package/infrastructure/{iam-policy-full.json → domains/security/templates/iam-policy-full.json} +0 -0
- /package/infrastructure/{run-discovery.js → scripts/run-discovery.js} +0 -0
package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecuteResourceImportUseCase - Execute CloudFormation Resource Import
|
|
3
|
+
*
|
|
4
|
+
* Application Layer - Use Case
|
|
5
|
+
*
|
|
6
|
+
* Business logic for executing CloudFormation import operations for orphaned resources.
|
|
7
|
+
* Orchestrates the complete import workflow including template generation, change set
|
|
8
|
+
* creation, execution monitoring, and verification.
|
|
9
|
+
*
|
|
10
|
+
* Responsibilities:
|
|
11
|
+
* - Generate import template from resources and build template
|
|
12
|
+
* - Create and execute CloudFormation import change set
|
|
13
|
+
* - Monitor import progress with resource-level updates
|
|
14
|
+
* - Verify imported resources are present in stack
|
|
15
|
+
* - Report detailed progress and results
|
|
16
|
+
*
|
|
17
|
+
* Based on: SPEC-IMPORT-EXECUTION.md (lines 712-867)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
class ExecuteResourceImportUseCase {
|
|
21
|
+
/**
|
|
22
|
+
* Create use case with required dependencies
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} params
|
|
25
|
+
* @param {Object} params.importTemplateGenerator - Generates import templates
|
|
26
|
+
* @param {Object} params.importProgressMonitor - Monitors import operations
|
|
27
|
+
* @param {Object} params.cloudFormationRepository - CloudFormation operations
|
|
28
|
+
* @param {Object} params.stackRepository - Stack template operations
|
|
29
|
+
*/
|
|
30
|
+
constructor({ importTemplateGenerator, importProgressMonitor, cloudFormationRepository, stackRepository }) {
|
|
31
|
+
if (!importTemplateGenerator) {
|
|
32
|
+
throw new Error('importTemplateGenerator is required');
|
|
33
|
+
}
|
|
34
|
+
if (!importProgressMonitor) {
|
|
35
|
+
throw new Error('importProgressMonitor is required');
|
|
36
|
+
}
|
|
37
|
+
if (!cloudFormationRepository) {
|
|
38
|
+
throw new Error('cloudFormationRepository is required');
|
|
39
|
+
}
|
|
40
|
+
if (!stackRepository) {
|
|
41
|
+
throw new Error('stackRepository is required');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.templateGenerator = importTemplateGenerator;
|
|
45
|
+
this.progressMonitor = importProgressMonitor;
|
|
46
|
+
this.cfRepo = cloudFormationRepository;
|
|
47
|
+
this.stackRepo = stackRepository;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Execute complete CloudFormation import workflow
|
|
52
|
+
*
|
|
53
|
+
* Orchestrates the full import process:
|
|
54
|
+
* 1. Generate import template
|
|
55
|
+
* 2. Create CloudFormation change set
|
|
56
|
+
* 3. Wait for change set to be ready
|
|
57
|
+
* 4. Execute change set
|
|
58
|
+
* 5. Monitor import progress
|
|
59
|
+
* 6. Verify imported resources
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} params
|
|
62
|
+
* @param {Object} params.stackIdentifier - Stack name and region
|
|
63
|
+
* @param {Array<Object>} params.resourcesToImport - Resources to import
|
|
64
|
+
* @param {string} params.buildTemplatePath - Path to build template
|
|
65
|
+
* @param {Function} [params.onProgress] - Progress callback
|
|
66
|
+
* @returns {Promise<Object>} Import result with verification details
|
|
67
|
+
*/
|
|
68
|
+
async execute({ stackIdentifier, resourcesToImport, buildTemplatePath, onProgress }) {
|
|
69
|
+
try {
|
|
70
|
+
// Step 1: Generate import template
|
|
71
|
+
if (onProgress) {
|
|
72
|
+
onProgress({ step: 'generate_template', status: 'in_progress' });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { template, resourceIdentifiers } = await this.templateGenerator.generateImportTemplate({
|
|
76
|
+
resourcesToImport,
|
|
77
|
+
buildTemplatePath,
|
|
78
|
+
stackIdentifier,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (onProgress) {
|
|
82
|
+
onProgress({ step: 'generate_template', status: 'complete' });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Step 2: Create CloudFormation change set
|
|
86
|
+
if (onProgress) {
|
|
87
|
+
onProgress({ step: 'create_change_set', status: 'in_progress' });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const changeSetName = `import-orphaned-resources-${Date.now()}`;
|
|
91
|
+
const changeSet = await this.cfRepo.createChangeSet({
|
|
92
|
+
stackIdentifier,
|
|
93
|
+
changeSetName,
|
|
94
|
+
changeSetType: 'IMPORT',
|
|
95
|
+
template,
|
|
96
|
+
resourcesToImport: resourceIdentifiers,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (onProgress) {
|
|
100
|
+
onProgress({
|
|
101
|
+
step: 'create_change_set',
|
|
102
|
+
status: 'complete',
|
|
103
|
+
changeSetName,
|
|
104
|
+
changeSetId: changeSet.Id,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Step 3: Wait for change set to be ready
|
|
109
|
+
if (onProgress) {
|
|
110
|
+
onProgress({ step: 'wait_change_set', status: 'in_progress' });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await this.cfRepo.waitForChangeSet({ stackIdentifier, changeSetName });
|
|
114
|
+
|
|
115
|
+
if (onProgress) {
|
|
116
|
+
onProgress({ step: 'wait_change_set', status: 'complete' });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Step 4: Execute change set
|
|
120
|
+
if (onProgress) {
|
|
121
|
+
onProgress({ step: 'execute_import', status: 'in_progress' });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
await this.cfRepo.executeChangeSet({ stackIdentifier, changeSetName });
|
|
125
|
+
|
|
126
|
+
// Step 5: Monitor import progress
|
|
127
|
+
const resourceLogicalIds = resourcesToImport.map((r) => r.logicalId);
|
|
128
|
+
const importResult = await this.progressMonitor.monitorImport({
|
|
129
|
+
stackIdentifier,
|
|
130
|
+
resourceLogicalIds,
|
|
131
|
+
onProgress: (progress) => {
|
|
132
|
+
if (onProgress) {
|
|
133
|
+
onProgress({
|
|
134
|
+
step: 'execute_import',
|
|
135
|
+
status: 'in_progress',
|
|
136
|
+
resourceProgress: progress,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (onProgress) {
|
|
143
|
+
onProgress({ step: 'execute_import', status: 'complete' });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Step 6: Verify imported resources
|
|
147
|
+
if (onProgress) {
|
|
148
|
+
onProgress({ step: 'verify', status: 'in_progress' });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const verification = await this._verifyImportedResources({
|
|
152
|
+
stackIdentifier,
|
|
153
|
+
resourceLogicalIds,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (onProgress) {
|
|
157
|
+
onProgress({ step: 'verify', status: 'complete' });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Return success result with verification details
|
|
161
|
+
return {
|
|
162
|
+
success: true,
|
|
163
|
+
importedCount: importResult.importedCount,
|
|
164
|
+
failedCount: importResult.failedCount,
|
|
165
|
+
changeSetName,
|
|
166
|
+
stackStatus: verification.stackStatus,
|
|
167
|
+
verifiedResources: verification.resources,
|
|
168
|
+
};
|
|
169
|
+
} catch (error) {
|
|
170
|
+
// Return error with step information
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
error: error.message,
|
|
174
|
+
step: error.step || 'unknown',
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Verify that imported resources are present in the CloudFormation stack
|
|
181
|
+
*
|
|
182
|
+
* Checks that each logical ID corresponds to an actual resource in the stack
|
|
183
|
+
* and retrieves physical IDs and resource types for verification.
|
|
184
|
+
*
|
|
185
|
+
* @param {Object} params
|
|
186
|
+
* @param {Object} params.stackIdentifier - Stack name and region
|
|
187
|
+
* @param {Array<string>} params.resourceLogicalIds - Logical IDs to verify
|
|
188
|
+
* @returns {Promise<Object>} Verification result with resource details
|
|
189
|
+
* @private
|
|
190
|
+
*/
|
|
191
|
+
async _verifyImportedResources({ stackIdentifier, resourceLogicalIds }) {
|
|
192
|
+
// Get all resources from the stack
|
|
193
|
+
const stackResources = await this.cfRepo.getStackResources(stackIdentifier);
|
|
194
|
+
|
|
195
|
+
// Map each logical ID to its verification status
|
|
196
|
+
const verifiedResources = resourceLogicalIds.map((logicalId) => {
|
|
197
|
+
const resource = stackResources.find((r) => r.LogicalResourceId === logicalId);
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
logicalId,
|
|
201
|
+
verified: !!resource,
|
|
202
|
+
physicalId: resource?.PhysicalResourceId,
|
|
203
|
+
resourceType: resource?.ResourceType,
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Check if all resources were verified
|
|
208
|
+
const allVerified = verifiedResources.every((r) => r.verified);
|
|
209
|
+
|
|
210
|
+
// Get current stack status
|
|
211
|
+
const stackStatus = await this.cfRepo.getStackStatus(stackIdentifier);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
allVerified,
|
|
215
|
+
resources: verifiedResources,
|
|
216
|
+
stackStatus,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
module.exports = ExecuteResourceImportUseCase;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReconcilePropertiesUseCase - Reconcile Property Drift
|
|
3
|
+
*
|
|
4
|
+
* Application Layer - Use Case
|
|
5
|
+
*
|
|
6
|
+
* Business logic for the "frigg repair --reconcile" command. Orchestrates property
|
|
7
|
+
* drift reconciliation to fix mutable property mismatches between CloudFormation
|
|
8
|
+
* template and actual cloud resources.
|
|
9
|
+
*
|
|
10
|
+
* Responsibilities:
|
|
11
|
+
* - Validate properties can be reconciled
|
|
12
|
+
* - Preview reconciliation impact
|
|
13
|
+
* - Execute reconciliation (template mode or resource mode)
|
|
14
|
+
* - Handle batch reconciliations
|
|
15
|
+
* - Skip immutable properties
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
class ReconcilePropertiesUseCase {
|
|
19
|
+
/**
|
|
20
|
+
* Create use case with required dependencies
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} params
|
|
23
|
+
* @param {IPropertyReconciler} params.propertyReconciler - Property reconciliation operations
|
|
24
|
+
*/
|
|
25
|
+
constructor({ propertyReconciler }) {
|
|
26
|
+
if (!propertyReconciler) {
|
|
27
|
+
throw new Error('propertyReconciler is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.propertyReconciler = propertyReconciler;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Reconcile a single property mismatch
|
|
35
|
+
*
|
|
36
|
+
* @param {Object} params
|
|
37
|
+
* @param {StackIdentifier} params.stackIdentifier - Stack identifier
|
|
38
|
+
* @param {string} params.logicalId - Logical resource ID
|
|
39
|
+
* @param {PropertyMismatch} params.mismatch - Property mismatch to reconcile
|
|
40
|
+
* @param {string} [params.mode='template'] - Reconciliation mode
|
|
41
|
+
* @returns {Promise<Object>} Reconciliation result
|
|
42
|
+
*/
|
|
43
|
+
async reconcileSingleProperty({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
|
|
44
|
+
// 1. Check if property can be reconciled
|
|
45
|
+
const canReconcile = await this.propertyReconciler.canReconcile(mismatch);
|
|
46
|
+
|
|
47
|
+
if (!canReconcile) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Property ${mismatch.propertyPath} cannot be reconciled automatically (immutable property requires replacement)`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 2. Execute reconciliation
|
|
54
|
+
const result = await this.propertyReconciler.reconcileProperty({
|
|
55
|
+
stackIdentifier,
|
|
56
|
+
logicalId,
|
|
57
|
+
mismatch,
|
|
58
|
+
mode,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Reconcile multiple property mismatches for a resource
|
|
66
|
+
*
|
|
67
|
+
* @param {Object} params
|
|
68
|
+
* @param {StackIdentifier} params.stackIdentifier - Stack identifier
|
|
69
|
+
* @param {string} params.logicalId - Logical resource ID
|
|
70
|
+
* @param {string} [params.physicalId] - Physical resource ID (required for resource mode)
|
|
71
|
+
* @param {string} [params.resourceType] - Resource type (required for resource mode)
|
|
72
|
+
* @param {PropertyMismatch[]} params.mismatches - Property mismatches to reconcile
|
|
73
|
+
* @param {string} [params.mode='template'] - Reconciliation mode
|
|
74
|
+
* @returns {Promise<Object>} Batch reconciliation result
|
|
75
|
+
*/
|
|
76
|
+
async reconcileMultipleProperties({
|
|
77
|
+
stackIdentifier,
|
|
78
|
+
logicalId,
|
|
79
|
+
physicalId,
|
|
80
|
+
resourceType,
|
|
81
|
+
mismatches,
|
|
82
|
+
mode = 'template',
|
|
83
|
+
}) {
|
|
84
|
+
// 1. Filter out immutable properties (cannot be reconciled)
|
|
85
|
+
const reconcilableProperties = [];
|
|
86
|
+
const skippedProperties = [];
|
|
87
|
+
|
|
88
|
+
for (const mismatch of mismatches) {
|
|
89
|
+
const canReconcile = await this.propertyReconciler.canReconcile(mismatch);
|
|
90
|
+
|
|
91
|
+
if (canReconcile) {
|
|
92
|
+
reconcilableProperties.push(mismatch);
|
|
93
|
+
} else {
|
|
94
|
+
skippedProperties.push(mismatch);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 2. If no properties can be reconciled, return early
|
|
99
|
+
if (reconcilableProperties.length === 0) {
|
|
100
|
+
return {
|
|
101
|
+
reconciledCount: 0,
|
|
102
|
+
failedCount: 0,
|
|
103
|
+
skippedCount: skippedProperties.length,
|
|
104
|
+
reconcilableCount: 0,
|
|
105
|
+
message: `All ${mismatches.length} property mismatch(es) require resource replacement (immutable)`,
|
|
106
|
+
results: [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 3. Reconcile the reconcilable properties
|
|
111
|
+
const batchResult = await this.propertyReconciler.reconcileMultipleProperties({
|
|
112
|
+
stackIdentifier,
|
|
113
|
+
logicalId,
|
|
114
|
+
physicalId,
|
|
115
|
+
resourceType,
|
|
116
|
+
mismatches: reconcilableProperties,
|
|
117
|
+
mode,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 4. Return combined result
|
|
121
|
+
return {
|
|
122
|
+
reconciledCount: batchResult.reconciledCount,
|
|
123
|
+
failedCount: batchResult.failedCount,
|
|
124
|
+
skippedCount: skippedProperties.length,
|
|
125
|
+
reconcilableCount: reconcilableProperties.length,
|
|
126
|
+
message: batchResult.message,
|
|
127
|
+
results: batchResult.results,
|
|
128
|
+
skippedProperties: skippedProperties.length > 0 ? skippedProperties : undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Preview reconciliation without applying changes
|
|
134
|
+
*
|
|
135
|
+
* @param {Object} params
|
|
136
|
+
* @param {StackIdentifier} params.stackIdentifier - Stack identifier
|
|
137
|
+
* @param {string} params.logicalId - Logical resource ID
|
|
138
|
+
* @param {PropertyMismatch} params.mismatch - Property mismatch to preview
|
|
139
|
+
* @param {string} [params.mode='template'] - Reconciliation mode
|
|
140
|
+
* @returns {Promise<Object>} Preview result
|
|
141
|
+
*/
|
|
142
|
+
async previewReconciliation({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
|
|
143
|
+
return await this.propertyReconciler.previewReconciliation({
|
|
144
|
+
stackIdentifier,
|
|
145
|
+
logicalId,
|
|
146
|
+
mismatch,
|
|
147
|
+
mode,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
module.exports = ReconcilePropertiesUseCase;
|