@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
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWSResourceImporter - AWS CloudFormation Resource Import Adapter
|
|
3
|
+
*
|
|
4
|
+
* Infrastructure Adapter - Hexagonal Architecture
|
|
5
|
+
*
|
|
6
|
+
* Implements IResourceImporter port for AWS CloudFormation.
|
|
7
|
+
* Handles resource import operations using CloudFormation change sets.
|
|
8
|
+
*
|
|
9
|
+
* Lazy-loads AWS SDK to minimize cold start time and memory usage.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const IResourceImporter = require('../../application/ports/IResourceImporter');
|
|
13
|
+
|
|
14
|
+
// Lazy-loaded AWS SDK CloudFormation client
|
|
15
|
+
let CloudFormationClient,
|
|
16
|
+
CreateChangeSetCommand,
|
|
17
|
+
DescribeChangeSetCommand,
|
|
18
|
+
ExecuteChangeSetCommand,
|
|
19
|
+
GetTemplateCommand;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Lazy load CloudFormation SDK
|
|
23
|
+
*/
|
|
24
|
+
function loadCloudFormation() {
|
|
25
|
+
if (!CloudFormationClient) {
|
|
26
|
+
const cfModule = require('@aws-sdk/client-cloudformation');
|
|
27
|
+
CloudFormationClient = cfModule.CloudFormationClient;
|
|
28
|
+
CreateChangeSetCommand = cfModule.CreateChangeSetCommand;
|
|
29
|
+
DescribeChangeSetCommand = cfModule.DescribeChangeSetCommand;
|
|
30
|
+
ExecuteChangeSetCommand = cfModule.ExecuteChangeSetCommand;
|
|
31
|
+
GetTemplateCommand = cfModule.GetTemplateCommand;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class AWSResourceImporter extends IResourceImporter {
|
|
36
|
+
/**
|
|
37
|
+
* Resource types that support import
|
|
38
|
+
* Maps CloudFormation resource type to identifier property
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
static IMPORTABLE_TYPES = {
|
|
42
|
+
'AWS::EC2::VPC': 'VpcId',
|
|
43
|
+
'AWS::EC2::Subnet': 'SubnetId',
|
|
44
|
+
'AWS::EC2::SecurityGroup': 'GroupId',
|
|
45
|
+
'AWS::EC2::RouteTable': 'RouteTableId',
|
|
46
|
+
'AWS::RDS::DBCluster': 'DBClusterIdentifier',
|
|
47
|
+
'AWS::KMS::Key': 'KeyId',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Create AWS Resource Importer
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} [config={}]
|
|
54
|
+
* @param {string} [config.region] - AWS region (defaults to AWS_REGION env var)
|
|
55
|
+
*/
|
|
56
|
+
constructor(config = {}) {
|
|
57
|
+
super();
|
|
58
|
+
this.region = config.region || process.env.AWS_REGION || 'us-east-1';
|
|
59
|
+
this.client = null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get or create CloudFormation client
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
_getClient() {
|
|
67
|
+
if (!this.client) {
|
|
68
|
+
loadCloudFormation();
|
|
69
|
+
this.client = new CloudFormationClient({ region: this.region });
|
|
70
|
+
}
|
|
71
|
+
return this.client;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Check if a resource type supports import
|
|
76
|
+
*/
|
|
77
|
+
async supportsImport(resourceType) {
|
|
78
|
+
return resourceType in AWSResourceImporter.IMPORTABLE_TYPES;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the identifier property for a resource type
|
|
83
|
+
*/
|
|
84
|
+
async getIdentifierProperty(resourceType) {
|
|
85
|
+
if (!(await this.supportsImport(resourceType))) {
|
|
86
|
+
throw new Error(`Resource type ${resourceType} does not support import`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return AWSResourceImporter.IMPORTABLE_TYPES[resourceType];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Validate that a resource can be imported
|
|
94
|
+
*/
|
|
95
|
+
async validateImport({ resourceType, physicalId, region }) {
|
|
96
|
+
const canImport = await this.supportsImport(resourceType);
|
|
97
|
+
|
|
98
|
+
if (!canImport) {
|
|
99
|
+
return {
|
|
100
|
+
canImport: false,
|
|
101
|
+
reason: `Resource type ${resourceType} is not supported for import`,
|
|
102
|
+
warnings: [],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Add resource-specific warnings
|
|
107
|
+
const warnings = [];
|
|
108
|
+
if (resourceType === 'AWS::RDS::DBCluster') {
|
|
109
|
+
warnings.push(
|
|
110
|
+
'Ensure DBCluster has required properties (Engine, MasterUsername, etc.)'
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
canImport: true,
|
|
116
|
+
reason: '',
|
|
117
|
+
warnings,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Import a single resource into a stack
|
|
123
|
+
*/
|
|
124
|
+
async importResource({ stackIdentifier, logicalId, resourceType, physicalId, properties }) {
|
|
125
|
+
// Validate resource type
|
|
126
|
+
if (!(await this.supportsImport(resourceType))) {
|
|
127
|
+
throw new Error(`Resource type ${resourceType} does not support import`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const client = this._getClient();
|
|
131
|
+
|
|
132
|
+
// Get identifier property
|
|
133
|
+
const identifierProperty = await this.getIdentifierProperty(resourceType);
|
|
134
|
+
|
|
135
|
+
// Create change set for import
|
|
136
|
+
const changeSetName = `import-${logicalId}-${Date.now()}`;
|
|
137
|
+
|
|
138
|
+
const createChangeSetCommand = new CreateChangeSetCommand({
|
|
139
|
+
StackName: stackIdentifier.stackName,
|
|
140
|
+
ChangeSetName: changeSetName,
|
|
141
|
+
ChangeSetType: 'IMPORT',
|
|
142
|
+
ResourcesToImport: [
|
|
143
|
+
{
|
|
144
|
+
ResourceType: resourceType,
|
|
145
|
+
LogicalResourceId: logicalId,
|
|
146
|
+
ResourceIdentifier: {
|
|
147
|
+
[identifierProperty]: physicalId,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
TemplateBody: JSON.stringify({
|
|
152
|
+
Resources: {
|
|
153
|
+
[logicalId]: {
|
|
154
|
+
Type: resourceType,
|
|
155
|
+
Properties: properties,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
}),
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const createResponse = await client.send(createChangeSetCommand);
|
|
162
|
+
|
|
163
|
+
// Execute the change set
|
|
164
|
+
const executeCommand = new ExecuteChangeSetCommand({
|
|
165
|
+
ChangeSetName: changeSetName,
|
|
166
|
+
StackName: stackIdentifier.stackName,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
await client.send(executeCommand);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
operationId: createResponse.Id,
|
|
173
|
+
status: 'IN_PROGRESS',
|
|
174
|
+
message: `Resource import initiated via change set ${createResponse.Id}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Import multiple resources into a stack in a single operation
|
|
180
|
+
*/
|
|
181
|
+
async importMultipleResources({ stackIdentifier, resources }) {
|
|
182
|
+
const client = this._getClient();
|
|
183
|
+
|
|
184
|
+
// Filter to only supported resources
|
|
185
|
+
const supportedResources = [];
|
|
186
|
+
const unsupportedResources = [];
|
|
187
|
+
|
|
188
|
+
for (const resource of resources) {
|
|
189
|
+
if (await this.supportsImport(resource.resourceType)) {
|
|
190
|
+
supportedResources.push(resource);
|
|
191
|
+
} else {
|
|
192
|
+
unsupportedResources.push(resource);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (supportedResources.length === 0) {
|
|
197
|
+
return {
|
|
198
|
+
operationId: null,
|
|
199
|
+
status: 'FAILED',
|
|
200
|
+
importedCount: 0,
|
|
201
|
+
failedCount: resources.length,
|
|
202
|
+
message: 'No supported resources to import',
|
|
203
|
+
details: [],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Build resources to import
|
|
208
|
+
const resourcesToImport = [];
|
|
209
|
+
const templateResources = {};
|
|
210
|
+
|
|
211
|
+
for (const resource of supportedResources) {
|
|
212
|
+
const identifierProperty = await this.getIdentifierProperty(resource.resourceType);
|
|
213
|
+
|
|
214
|
+
resourcesToImport.push({
|
|
215
|
+
ResourceType: resource.resourceType,
|
|
216
|
+
LogicalResourceId: resource.logicalId,
|
|
217
|
+
ResourceIdentifier: {
|
|
218
|
+
[identifierProperty]: resource.physicalId,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
templateResources[resource.logicalId] = {
|
|
223
|
+
Type: resource.resourceType,
|
|
224
|
+
Properties: resource.properties,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Create change set for import
|
|
229
|
+
const changeSetName = `import-multi-${Date.now()}`;
|
|
230
|
+
|
|
231
|
+
const createChangeSetCommand = new CreateChangeSetCommand({
|
|
232
|
+
StackName: stackIdentifier.stackName,
|
|
233
|
+
ChangeSetName: changeSetName,
|
|
234
|
+
ChangeSetType: 'IMPORT',
|
|
235
|
+
ResourcesToImport: resourcesToImport,
|
|
236
|
+
TemplateBody: JSON.stringify({
|
|
237
|
+
Resources: templateResources,
|
|
238
|
+
}),
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const createResponse = await client.send(createChangeSetCommand);
|
|
242
|
+
|
|
243
|
+
// Execute the change set
|
|
244
|
+
const executeCommand = new ExecuteChangeSetCommand({
|
|
245
|
+
ChangeSetName: changeSetName,
|
|
246
|
+
StackName: stackIdentifier.stackName,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
await client.send(executeCommand);
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
operationId: createResponse.Id,
|
|
253
|
+
status: 'IN_PROGRESS',
|
|
254
|
+
importedCount: supportedResources.length,
|
|
255
|
+
failedCount: unsupportedResources.length,
|
|
256
|
+
message: `Import operation initiated for ${supportedResources.length} resources`,
|
|
257
|
+
details: [],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get status of an import operation
|
|
263
|
+
*/
|
|
264
|
+
async getImportStatus(operationId) {
|
|
265
|
+
const client = this._getClient();
|
|
266
|
+
|
|
267
|
+
const command = new DescribeChangeSetCommand({
|
|
268
|
+
ChangeSetName: operationId,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const response = await client.send(command);
|
|
272
|
+
|
|
273
|
+
// Map CloudFormation status to our status
|
|
274
|
+
let status = 'IN_PROGRESS';
|
|
275
|
+
let progress = 0;
|
|
276
|
+
|
|
277
|
+
if (response.ExecutionStatus === 'EXECUTE_COMPLETE') {
|
|
278
|
+
status = 'COMPLETE';
|
|
279
|
+
progress = 100;
|
|
280
|
+
} else if (response.Status === 'FAILED' || response.ExecutionStatus === 'EXECUTE_FAILED') {
|
|
281
|
+
status = 'FAILED';
|
|
282
|
+
progress = 0;
|
|
283
|
+
} else if (response.Status === 'CREATE_COMPLETE') {
|
|
284
|
+
status = 'IN_PROGRESS';
|
|
285
|
+
progress = 50;
|
|
286
|
+
} else if (response.Status === 'CREATE_PENDING') {
|
|
287
|
+
status = 'IN_PROGRESS';
|
|
288
|
+
progress = 25;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
operationId,
|
|
293
|
+
status,
|
|
294
|
+
progress,
|
|
295
|
+
message: response.StatusReason || '',
|
|
296
|
+
completedTime: status === 'COMPLETE' ? response.CreationTime : null,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Generate CloudFormation template snippet for an imported resource
|
|
302
|
+
*/
|
|
303
|
+
async generateTemplateSnippet({ logicalId, resourceType, properties }) {
|
|
304
|
+
// Validate resource type
|
|
305
|
+
if (!(await this.supportsImport(resourceType))) {
|
|
306
|
+
throw new Error(`Resource type ${resourceType} does not support import`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
[logicalId]: {
|
|
311
|
+
Type: resourceType,
|
|
312
|
+
Properties: properties,
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
module.exports = AWSResourceImporter;
|