@friggframework/devtools 2.0.0-next.44 → 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 -2074
- /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
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# Orphan Detection: Relationship Analysis & Multiple Resource Warning System
|
|
2
|
+
|
|
3
|
+
## Problem Statement
|
|
4
|
+
|
|
5
|
+
When `frigg doctor` detects multiple orphaned resources of the same type (e.g., 3 VPCs, 10 subnets), users cannot easily determine:
|
|
6
|
+
1. Which orphaned resources are actually relevant to import
|
|
7
|
+
2. Which orphaned resources are old/unused and should be deleted
|
|
8
|
+
3. Whether any orphaned resources are being actively referenced by drifted resources
|
|
9
|
+
|
|
10
|
+
## Real-World Example: acme-integrations-dev Stack
|
|
11
|
+
|
|
12
|
+
### AWS Reality (Verified 2025-10-27)
|
|
13
|
+
|
|
14
|
+
**CloudFormation Stack State:**
|
|
15
|
+
- Stack Name: `acme-integrations-dev`
|
|
16
|
+
- VPCs in stack: **0** (stack doesn't manage VPC)
|
|
17
|
+
- Lambda functions: 16 (all with VPC configuration drift)
|
|
18
|
+
|
|
19
|
+
**Lambda Functions Configuration:**
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"VpcId": "vpc-01f21101d4ed6db59", // AWS Default VPC (172.31.0.0/16)
|
|
23
|
+
"SubnetIds": [
|
|
24
|
+
"subnet-020d32e3ca398a041", // In default VPC
|
|
25
|
+
"subnet-0c186318804aba790" // In default VPC
|
|
26
|
+
],
|
|
27
|
+
"SecurityGroupIds": [
|
|
28
|
+
"sg-0aca40438d17344c4" // In default VPC
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Orphaned Resources Detected:**
|
|
34
|
+
|
|
35
|
+
**3 VPCs (ALL with Frigg CloudFormation tags):**
|
|
36
|
+
1. `vpc-0eadd96976d29ede7` (10.0.0.0/16)
|
|
37
|
+
- Tags: `aws:cloudformation:stack-name=acme-integrations-dev`, `aws:cloudformation:logical-id=FriggVPC`
|
|
38
|
+
- Status: **NOT in CloudFormation stack, NOT used by Lambdas**
|
|
39
|
+
- Conclusion: **Old unused VPC, should be deleted**
|
|
40
|
+
|
|
41
|
+
2. `vpc-0e2351eac99adcb83` (10.0.0.0/16)
|
|
42
|
+
- Tags: `aws:cloudformation:stack-name=acme-integrations-dev`, `aws:cloudformation:logical-id=FriggVPC`
|
|
43
|
+
- Status: **NOT in CloudFormation stack, NOT used by Lambdas**
|
|
44
|
+
- Conclusion: **Old unused VPC, should be deleted**
|
|
45
|
+
|
|
46
|
+
3. `vpc-020a0365610c05f0b` (10.0.0.0/16)
|
|
47
|
+
- Tags: `aws:cloudformation:stack-name=acme-integrations-dev`, `aws:cloudformation:logical-id=FriggVPC`
|
|
48
|
+
- Status: **NOT in CloudFormation stack, NOT used by Lambdas**
|
|
49
|
+
- Conclusion: **Old unused VPC, should be deleted**
|
|
50
|
+
|
|
51
|
+
**10 Subnets:** All belong to the 3 orphaned VPCs (not the default VPC being used)
|
|
52
|
+
|
|
53
|
+
**3 Security Groups:** All belong to the 3 orphaned VPCs (not the default VPC being used)
|
|
54
|
+
|
|
55
|
+
### Key Insights
|
|
56
|
+
|
|
57
|
+
1. **CloudFormation tags are misleading**: All 3 VPCs have identical CFN tags but NONE are in the stack
|
|
58
|
+
2. **Lambda drift is expected**: Lambdas use default VPC which has NO Frigg tags
|
|
59
|
+
3. **All orphaned resources are unused**: None of the 16 orphaned resources are being referenced
|
|
60
|
+
4. **Old deployment artifacts**: The orphaned VPCs are likely from previous Frigg deployments that failed cleanup
|
|
61
|
+
|
|
62
|
+
## Solution Design
|
|
63
|
+
|
|
64
|
+
### Phase 1: Relationship Analysis
|
|
65
|
+
|
|
66
|
+
Analyze connections between:
|
|
67
|
+
- **Drift Issues** → Resources being referenced in actual values
|
|
68
|
+
- **Orphaned Resources** → Resources detected but not in stack
|
|
69
|
+
- **Resource Hierarchies** → VPCs contain subnets/SGs, subnets belong to VPCs
|
|
70
|
+
|
|
71
|
+
### Phase 2: Extract Referenced Resource IDs
|
|
72
|
+
|
|
73
|
+
From property mismatch drift issues, extract resource IDs that are **actually being used**:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// Example drift issue:
|
|
77
|
+
{
|
|
78
|
+
propertyPath: "VpcConfig.SubnetIds",
|
|
79
|
+
expectedValue: "subnet-old-1,subnet-old-2",
|
|
80
|
+
actualValue: "subnet-020d32e3ca398a041,subnet-0c186318804aba790"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Extract: ["subnet-020d32e3ca398a041", "subnet-0c186318804aba790"]
|
|
84
|
+
// These are the subnets actually being used (even if not orphaned)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Property Paths to Analyze:**
|
|
88
|
+
- `VpcConfig.SubnetIds` → Subnet IDs
|
|
89
|
+
- `VpcConfig.SecurityGroupIds` → Security Group IDs
|
|
90
|
+
- `VpcId` → VPC IDs
|
|
91
|
+
- `SubnetId` → Subnet IDs (for other resources)
|
|
92
|
+
|
|
93
|
+
### Phase 3: Build Resource Relationship Graph
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
{
|
|
97
|
+
orphanedResources: [
|
|
98
|
+
{
|
|
99
|
+
physicalId: "vpc-0eadd96976d29ede7",
|
|
100
|
+
resourceType: "AWS::EC2::VPC",
|
|
101
|
+
metadata: {
|
|
102
|
+
isReferencedByDrift: false, // NOT referenced in any drift
|
|
103
|
+
containsReferencedResources: false, // No subnets/SGs in this VPC are referenced
|
|
104
|
+
relatedOrphans: [ // Other orphans in this VPC
|
|
105
|
+
"subnet-0ad31b5ee6814b8fa",
|
|
106
|
+
"sg-03abddb7fb50aeaff"
|
|
107
|
+
],
|
|
108
|
+
priority: "LOW" // Unused, should delete not import
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
physicalId: "subnet-020d32e3ca398a041",
|
|
113
|
+
resourceType: "AWS::EC2::Subnet",
|
|
114
|
+
vpcId: "vpc-01f21101d4ed6db59", // In default VPC (not orphaned)
|
|
115
|
+
metadata: {
|
|
116
|
+
isReferencedByDrift: true, // ✅ Referenced by 16 Lambda functions
|
|
117
|
+
referencedBy: [ // Which resources reference this
|
|
118
|
+
"acme-integrations-dev-attio",
|
|
119
|
+
"acme-integrations-dev-auth",
|
|
120
|
+
// ... 14 more
|
|
121
|
+
],
|
|
122
|
+
priority: "N/A" // Not orphaned, just drift reference
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Phase 4: Multi-Resource Warning System
|
|
130
|
+
|
|
131
|
+
When multiple resources of the same type are detected, show contextual warnings:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
⚠ WARNING: Multiple VPCs detected (3 orphaned)
|
|
135
|
+
|
|
136
|
+
Analysis:
|
|
137
|
+
• vpc-0eadd96976d29ede7 - No active references, contains 3 orphaned subnets [UNUSED]
|
|
138
|
+
• vpc-0e2351eac99adcb83 - No active references, contains 4 orphaned subnets [UNUSED]
|
|
139
|
+
• vpc-020a0365610c05f0b - No active references, contains 3 orphaned subnets [UNUSED]
|
|
140
|
+
|
|
141
|
+
Recommendation:
|
|
142
|
+
❌ Do NOT import these VPCs - they are old deployment artifacts
|
|
143
|
+
✅ Lambda functions use default VPC (vpc-01f21101d4ed6db59) - drift is expected
|
|
144
|
+
🧹 Consider cleaning up orphaned VPCs to reduce clutter:
|
|
145
|
+
$ aws ec2 delete-vpc --vpc-id vpc-0eadd96976d29ede7
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Implementation Plan
|
|
149
|
+
|
|
150
|
+
### 1. Add Relationship Analysis to AWSResourceDetector
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
class AWSResourceDetector {
|
|
154
|
+
/**
|
|
155
|
+
* Find orphaned resources with relationship metadata
|
|
156
|
+
*/
|
|
157
|
+
async findOrphanedResourcesWithRelationships({
|
|
158
|
+
stackIdentifier,
|
|
159
|
+
stackResources,
|
|
160
|
+
driftIssues = []
|
|
161
|
+
}) {
|
|
162
|
+
// 1. Find orphaned resources (existing logic)
|
|
163
|
+
const orphans = await this.findOrphanedResources({
|
|
164
|
+
stackIdentifier,
|
|
165
|
+
stackResources
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// 2. Extract referenced resource IDs from drift
|
|
169
|
+
const referencedIds = this._extractReferencedResourceIds(driftIssues);
|
|
170
|
+
|
|
171
|
+
// 3. Enrich orphans with relationship metadata
|
|
172
|
+
return this._enrichWithRelationshipMetadata(orphans, referencedIds);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Extract resource IDs being referenced in drift actualValue
|
|
177
|
+
*/
|
|
178
|
+
_extractReferencedResourceIds(driftIssues) {
|
|
179
|
+
const referenced = {
|
|
180
|
+
vpcIds: new Set(),
|
|
181
|
+
subnetIds: new Set(),
|
|
182
|
+
securityGroupIds: new Set()
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
for (const issue of driftIssues) {
|
|
186
|
+
if (issue.type !== 'PROPERTY_MISMATCH') continue;
|
|
187
|
+
|
|
188
|
+
const { propertyPath, actualValue } = issue.mismatch;
|
|
189
|
+
|
|
190
|
+
// Extract subnet IDs from VpcConfig.SubnetIds
|
|
191
|
+
if (propertyPath === 'VpcConfig.SubnetIds') {
|
|
192
|
+
const subnetIds = actualValue.split(',');
|
|
193
|
+
subnetIds.forEach(id => referenced.subnetIds.add(id));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Extract SG IDs from VpcConfig.SecurityGroupIds
|
|
197
|
+
if (propertyPath === 'VpcConfig.SecurityGroupIds') {
|
|
198
|
+
const sgIds = actualValue.split(',');
|
|
199
|
+
sgIds.forEach(id => referenced.securityGroupIds.add(id));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
vpcIds: Array.from(referenced.vpcIds),
|
|
205
|
+
subnetIds: Array.from(referenced.subnetIds),
|
|
206
|
+
securityGroupIds: Array.from(referenced.securityGroupIds)
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Add relationship metadata to orphaned resources
|
|
212
|
+
*/
|
|
213
|
+
_enrichWithRelationshipMetadata(orphans, referencedIds) {
|
|
214
|
+
return orphans.map(orphan => {
|
|
215
|
+
const metadata = {
|
|
216
|
+
isReferencedByDrift: false,
|
|
217
|
+
referencedBy: [],
|
|
218
|
+
relatedOrphans: [],
|
|
219
|
+
priority: 'LOW'
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Check if this orphan is actually referenced
|
|
223
|
+
if (orphan.resourceType === 'AWS::EC2::Subnet') {
|
|
224
|
+
metadata.isReferencedByDrift = referencedIds.subnetIds.includes(orphan.physicalId);
|
|
225
|
+
} else if (orphan.resourceType === 'AWS::EC2::SecurityGroup') {
|
|
226
|
+
metadata.isReferencedByDrift = referencedIds.securityGroupIds.includes(orphan.physicalId);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (metadata.isReferencedByDrift) {
|
|
230
|
+
metadata.priority = 'HIGH';
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return { ...orphan, metadata };
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Analyze orphan summary for warnings
|
|
239
|
+
*/
|
|
240
|
+
analyzeOrphanSummary(orphans) {
|
|
241
|
+
const summary = {
|
|
242
|
+
warnings: [],
|
|
243
|
+
multipleResourceTypes: []
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Group by resource type
|
|
247
|
+
const grouped = {};
|
|
248
|
+
for (const orphan of orphans) {
|
|
249
|
+
grouped[orphan.resourceType] = grouped[orphan.resourceType] || [];
|
|
250
|
+
grouped[orphan.resourceType].push(orphan);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Check for multiples
|
|
254
|
+
for (const [type, resources] of Object.entries(grouped)) {
|
|
255
|
+
if (resources.length > 1) {
|
|
256
|
+
const shortType = type.replace('AWS::EC2::', '');
|
|
257
|
+
summary.warnings.push(
|
|
258
|
+
`Multiple ${shortType}s detected (${resources.length}). Review relationships before importing.`
|
|
259
|
+
);
|
|
260
|
+
summary.multipleResourceTypes.push(type);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return summary;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 2. Update Health Check to Use Relationship Analysis
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
// domains/health/application/use-cases/check-stack-health-use-case.js
|
|
273
|
+
|
|
274
|
+
class CheckStackHealthUseCase {
|
|
275
|
+
async execute({ stackName, region }) {
|
|
276
|
+
// ... existing drift detection ...
|
|
277
|
+
|
|
278
|
+
// Enhanced orphan detection with relationships
|
|
279
|
+
const orphanedResources = await this.resourceDetector.findOrphanedResourcesWithRelationships({
|
|
280
|
+
stackIdentifier,
|
|
281
|
+
stackResources,
|
|
282
|
+
driftIssues: issues // Pass drift issues for analysis
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Analyze for warnings
|
|
286
|
+
const orphanSummary = this.resourceDetector.analyzeOrphanSummary(orphanedResources);
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
// ... existing fields ...
|
|
290
|
+
orphanedResources,
|
|
291
|
+
orphanAnalysis: orphanSummary
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 3. Update Frigg Doctor Output
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
// Show relationship warnings
|
|
301
|
+
if (orphanAnalysis.warnings.length > 0) {
|
|
302
|
+
console.log('\n⚠ ORPHAN ANALYSIS WARNINGS:\n');
|
|
303
|
+
for (const warning of orphanAnalysis.warnings) {
|
|
304
|
+
console.log(` ${warning}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Show orphan details with metadata
|
|
309
|
+
console.log('\n CRITICAL ISSUES:');
|
|
310
|
+
for (const orphan of orphanedResources) {
|
|
311
|
+
console.log(` [ORPHANED_RESOURCE] ${orphan.physicalId}`);
|
|
312
|
+
console.log(` Resource: ${orphan.resourceType}`);
|
|
313
|
+
|
|
314
|
+
if (orphan.metadata) {
|
|
315
|
+
if (orphan.metadata.isReferencedByDrift) {
|
|
316
|
+
console.log(` ✅ ACTIVELY USED - Referenced by ${orphan.metadata.referencedBy.length} drifted resources`);
|
|
317
|
+
console.log(` Fix: Import to CloudFormation stack`);
|
|
318
|
+
} else {
|
|
319
|
+
console.log(` ❌ UNUSED - Not referenced by any stack resources`);
|
|
320
|
+
console.log(` Fix: Consider deleting instead of importing`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 4. Update Frigg Repair to Handle Multiples
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// frigg repair --import <stack-name>
|
|
330
|
+
|
|
331
|
+
if (orphanAnalysis.multipleResourceTypes.includes('AWS::EC2::VPC')) {
|
|
332
|
+
console.log('\n⚠ WARNING: Multiple VPCs detected');
|
|
333
|
+
console.log('Please review and select which VPC to import:\n');
|
|
334
|
+
|
|
335
|
+
const vpcs = orphanedResources.filter(o => o.resourceType === 'AWS::EC2::VPC');
|
|
336
|
+
for (let i = 0; i < vpcs.length; i++) {
|
|
337
|
+
const vpc = vpcs[i];
|
|
338
|
+
console.log(` ${i + 1}. ${vpc.physicalId} (${vpc.cidrBlock})`);
|
|
339
|
+
console.log(` Referenced: ${vpc.metadata.isReferencedByDrift ? 'Yes' : 'No'}`);
|
|
340
|
+
console.log(` Related Resources: ${vpc.metadata.relatedOrphans.length} subnets/SGs\n`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Prompt user to select or skip
|
|
344
|
+
const selection = await promptUser('Select VPC number to import (or "skip" to skip all): ');
|
|
345
|
+
|
|
346
|
+
if (selection === 'skip') {
|
|
347
|
+
console.log('Skipping VPC import');
|
|
348
|
+
// Remove VPCs from import list
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Testing Strategy
|
|
354
|
+
|
|
355
|
+
### Test 1: Detect Unused Orphans
|
|
356
|
+
✅ 3 VPCs with CFN tags but NOT in stack, NOT referenced → mark as unused
|
|
357
|
+
|
|
358
|
+
### Test 2: Detect Referenced Non-Orphans
|
|
359
|
+
✅ Subnets in default VPC referenced by Lambdas but NOT orphaned → show in analysis
|
|
360
|
+
|
|
361
|
+
### Test 3: Multi-Resource Warning
|
|
362
|
+
✅ Multiple VPCs detected → show warning + require user selection
|
|
363
|
+
|
|
364
|
+
### Test 4: VPC Hierarchy Analysis
|
|
365
|
+
✅ VPC contains subnets → link orphaned subnets to orphaned VPC
|
|
366
|
+
|
|
367
|
+
## Benefits
|
|
368
|
+
|
|
369
|
+
1. **Prevents Bad Imports**: Users won't accidentally import unused old VPCs
|
|
370
|
+
2. **Clarifies Drift**: Explains why drift exists (using default VPC vs Frigg VPC)
|
|
371
|
+
3. **Cleanup Guidance**: Identifies resources that should be deleted, not imported
|
|
372
|
+
4. **Informed Decisions**: Shows relationships between resources before action
|
|
373
|
+
5. **Reduces Errors**: Requires explicit selection when multiple resources exist
|
|
374
|
+
|
|
375
|
+
## Next Steps
|
|
376
|
+
|
|
377
|
+
1. ✅ Write TDD tests for relationship analysis
|
|
378
|
+
2. ⬜ Implement `findOrphanedResourcesWithRelationships` method
|
|
379
|
+
3. ⬜ Implement `_extractReferencedResourceIds` helper
|
|
380
|
+
4. ⬜ Implement `_enrichWithRelationshipMetadata` helper
|
|
381
|
+
5. ⬜ Implement `analyzeOrphanSummary` method
|
|
382
|
+
6. ⬜ Update `CheckStackHealthUseCase` to use new method
|
|
383
|
+
7. ⬜ Update `frigg doctor` output to show warnings
|
|
384
|
+
8. ⬜ Update `frigg repair` to handle multiple resources
|
|
385
|
+
9. ⬜ Test with real acme-integrations-dev data
|
|
386
|
+
10. ⬜ Document relationship analysis in HEALTH.md
|