@go-to-k/cdkd 0.91.3 → 0.91.4
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/dist/cli.js +78 -44
- package/dist/cli.js.map +2 -2
- package/dist/go-to-k-cdkd-0.91.4.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.91.3.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -79615,6 +79615,7 @@ import { Command as Command17 } from "commander";
|
|
|
79615
79615
|
import {
|
|
79616
79616
|
CreateChangeSetCommand,
|
|
79617
79617
|
DescribeChangeSetCommand,
|
|
79618
|
+
DescribeStackEventsCommand,
|
|
79618
79619
|
ExecuteChangeSetCommand,
|
|
79619
79620
|
DescribeStacksCommand as DescribeStacksCommand2,
|
|
79620
79621
|
DescribeTypeCommand,
|
|
@@ -79631,10 +79632,13 @@ var NEVER_IMPORTABLE_TYPES = /* @__PURE__ */ new Set([
|
|
|
79631
79632
|
function isNeverImportableType(resourceType) {
|
|
79632
79633
|
if (NEVER_IMPORTABLE_TYPES.has(resourceType))
|
|
79633
79634
|
return true;
|
|
79634
|
-
if (resourceType
|
|
79635
|
+
if (isCustomResourceType(resourceType))
|
|
79635
79636
|
return true;
|
|
79636
79637
|
return false;
|
|
79637
79638
|
}
|
|
79639
|
+
function isCustomResourceType(resourceType) {
|
|
79640
|
+
return resourceType === "AWS::CloudFormation::CustomResource" || resourceType.startsWith("Custom::");
|
|
79641
|
+
}
|
|
79638
79642
|
var PRIMARY_IDENTIFIER_FALLBACK = {
|
|
79639
79643
|
"AWS::S3::Bucket": "BucketName",
|
|
79640
79644
|
"AWS::IAM::Role": "RoleName",
|
|
@@ -79898,6 +79902,12 @@ async function exportCommand(stackArg, options) {
|
|
|
79898
79902
|
);
|
|
79899
79903
|
}
|
|
79900
79904
|
const phase1Template = filterTemplateForImport(template, phase1Imports);
|
|
79905
|
+
const injectedCount = injectDeletionPolicyForImport(phase1Template);
|
|
79906
|
+
if (injectedCount > 0) {
|
|
79907
|
+
logger.info(
|
|
79908
|
+
`Injected DeletionPolicy: Retain on ${injectedCount} resource(s) without an explicit DeletionPolicy (required by CFn IMPORT). The first \`cdk deploy\` after export will reset each to your CDK-declared value.`
|
|
79909
|
+
);
|
|
79910
|
+
}
|
|
79901
79911
|
await executeImportChangeSet(
|
|
79902
79912
|
awsClients.cloudFormation,
|
|
79903
79913
|
cfnStackName,
|
|
@@ -80029,7 +80039,7 @@ async function assertCfnStackAbsent(cfnClient, stackName) {
|
|
|
80029
80039
|
}
|
|
80030
80040
|
}
|
|
80031
80041
|
function isPhase2CreatableType(resourceType) {
|
|
80032
|
-
return resourceType
|
|
80042
|
+
return isCustomResourceType(resourceType);
|
|
80033
80043
|
}
|
|
80034
80044
|
async function buildImportPlan(state, template, cfnClient) {
|
|
80035
80045
|
const templateResources = template["Resources"];
|
|
@@ -80211,32 +80221,49 @@ function resolveTemplateParameters(template, userOverrides) {
|
|
|
80211
80221
|
}
|
|
80212
80222
|
return { parameters, missing };
|
|
80213
80223
|
}
|
|
80224
|
+
function injectDeletionPolicyForImport(template) {
|
|
80225
|
+
const resources = template["Resources"];
|
|
80226
|
+
if (!resources || typeof resources !== "object" || Array.isArray(resources)) {
|
|
80227
|
+
return 0;
|
|
80228
|
+
}
|
|
80229
|
+
let injected = 0;
|
|
80230
|
+
for (const [, resource] of Object.entries(resources)) {
|
|
80231
|
+
if (!resource || typeof resource !== "object" || Array.isArray(resource))
|
|
80232
|
+
continue;
|
|
80233
|
+
const r = resource;
|
|
80234
|
+
if (r["DeletionPolicy"] === void 0) {
|
|
80235
|
+
r["DeletionPolicy"] = "Retain";
|
|
80236
|
+
injected++;
|
|
80237
|
+
}
|
|
80238
|
+
}
|
|
80239
|
+
return injected;
|
|
80240
|
+
}
|
|
80214
80241
|
function filterTemplateForImport(template, plan) {
|
|
80215
|
-
const allow = new
|
|
80242
|
+
const allow = new Map(plan.map((p) => [p.logicalId, p]));
|
|
80216
80243
|
const original = template["Resources"];
|
|
80217
80244
|
const filteredResources = {};
|
|
80218
80245
|
for (const [logicalId, resource] of Object.entries(original)) {
|
|
80219
|
-
|
|
80220
|
-
|
|
80221
|
-
|
|
80246
|
+
const entry = allow.get(logicalId);
|
|
80247
|
+
if (!entry)
|
|
80248
|
+
continue;
|
|
80249
|
+
filteredResources[logicalId] = overlayResourceIdentifierOnProperties(resource, entry);
|
|
80222
80250
|
}
|
|
80223
80251
|
const result = { ...template, Resources: filteredResources };
|
|
80224
|
-
|
|
80225
|
-
if (outputs && typeof outputs === "object" && !Array.isArray(outputs)) {
|
|
80226
|
-
const filteredOutputs = {};
|
|
80227
|
-
for (const [name, output] of Object.entries(outputs)) {
|
|
80228
|
-
if (referencesOnly(output, allow)) {
|
|
80229
|
-
filteredOutputs[name] = output;
|
|
80230
|
-
}
|
|
80231
|
-
}
|
|
80232
|
-
if (Object.keys(filteredOutputs).length > 0) {
|
|
80233
|
-
result["Outputs"] = filteredOutputs;
|
|
80234
|
-
} else {
|
|
80235
|
-
delete result["Outputs"];
|
|
80236
|
-
}
|
|
80237
|
-
}
|
|
80252
|
+
delete result["Outputs"];
|
|
80238
80253
|
return result;
|
|
80239
80254
|
}
|
|
80255
|
+
function overlayResourceIdentifierOnProperties(resource, entry) {
|
|
80256
|
+
if (!resource || typeof resource !== "object" || Array.isArray(resource)) {
|
|
80257
|
+
return resource;
|
|
80258
|
+
}
|
|
80259
|
+
const r = resource;
|
|
80260
|
+
const existingProperties = r["Properties"];
|
|
80261
|
+
const properties = existingProperties && typeof existingProperties === "object" && !Array.isArray(existingProperties) ? { ...existingProperties } : {};
|
|
80262
|
+
for (const [field, value] of Object.entries(entry.resourceIdentifier)) {
|
|
80263
|
+
properties[field] = value;
|
|
80264
|
+
}
|
|
80265
|
+
return { ...r, Properties: properties };
|
|
80266
|
+
}
|
|
80240
80267
|
function reportDriftBaselineGaps(state, logger) {
|
|
80241
80268
|
const entries = Object.entries(state.resources ?? {});
|
|
80242
80269
|
if (entries.length === 0)
|
|
@@ -80307,29 +80334,6 @@ function walkForGetStackOutput(node, path3, emit) {
|
|
|
80307
80334
|
walkForGetStackOutput(value, path3 ? `${path3}.${key}` : key, emit);
|
|
80308
80335
|
}
|
|
80309
80336
|
}
|
|
80310
|
-
function referencesOnly(node, allow) {
|
|
80311
|
-
if (!node || typeof node !== "object")
|
|
80312
|
-
return true;
|
|
80313
|
-
if (Array.isArray(node)) {
|
|
80314
|
-
return node.every((item) => referencesOnly(item, allow));
|
|
80315
|
-
}
|
|
80316
|
-
for (const [key, value] of Object.entries(node)) {
|
|
80317
|
-
if (key === "Ref" && typeof value === "string") {
|
|
80318
|
-
if (!allow.has(value))
|
|
80319
|
-
return false;
|
|
80320
|
-
continue;
|
|
80321
|
-
}
|
|
80322
|
-
if (key === "Fn::GetAtt") {
|
|
80323
|
-
const target = Array.isArray(value) && typeof value[0] === "string" ? value[0] : typeof value === "string" ? value.split(".")[0] : void 0;
|
|
80324
|
-
if (target && !allow.has(target))
|
|
80325
|
-
return false;
|
|
80326
|
-
continue;
|
|
80327
|
-
}
|
|
80328
|
-
if (!referencesOnly(value, allow))
|
|
80329
|
-
return false;
|
|
80330
|
-
}
|
|
80331
|
-
return true;
|
|
80332
|
-
}
|
|
80333
80337
|
function printPlan(plan, cfnStackName) {
|
|
80334
80338
|
const logger = getLogger();
|
|
80335
80339
|
logger.info("");
|
|
@@ -80407,11 +80411,41 @@ async function executeImportChangeSet(cfnClient, stackName, template, plan, para
|
|
|
80407
80411
|
{ StackName: stackName }
|
|
80408
80412
|
);
|
|
80409
80413
|
} catch (err) {
|
|
80414
|
+
const failureSummary = await collectImportFailureSummary(cfnClient, stackName).catch(() => "");
|
|
80410
80415
|
await cfnClient.send(new DeleteChangeSetCommand({ StackName: stackName, ChangeSetName: changeSetName })).catch(() => {
|
|
80411
80416
|
});
|
|
80417
|
+
if (failureSummary) {
|
|
80418
|
+
throw new Error(`IMPORT changeset failed:
|
|
80419
|
+
${failureSummary}`, { cause: err });
|
|
80420
|
+
}
|
|
80412
80421
|
throw err;
|
|
80413
80422
|
}
|
|
80414
80423
|
}
|
|
80424
|
+
async function collectImportFailureSummary(cfnClient, stackName) {
|
|
80425
|
+
const resp = await cfnClient.send(new DescribeStackEventsCommand({ StackName: stackName }));
|
|
80426
|
+
const events = resp.StackEvents ?? [];
|
|
80427
|
+
const failures = [];
|
|
80428
|
+
const seen = /* @__PURE__ */ new Set();
|
|
80429
|
+
for (const e of events) {
|
|
80430
|
+
if (!e.ResourceStatus || !e.ResourceStatus.endsWith("FAILED"))
|
|
80431
|
+
continue;
|
|
80432
|
+
if (!e.LogicalResourceId)
|
|
80433
|
+
continue;
|
|
80434
|
+
if (seen.has(e.LogicalResourceId))
|
|
80435
|
+
continue;
|
|
80436
|
+
seen.add(e.LogicalResourceId);
|
|
80437
|
+
failures.push({
|
|
80438
|
+
logicalId: e.LogicalResourceId,
|
|
80439
|
+
type: e.ResourceType ?? "<unknown>",
|
|
80440
|
+
reason: e.ResourceStatusReason ?? "<no reason reported>"
|
|
80441
|
+
});
|
|
80442
|
+
if (failures.length >= 5)
|
|
80443
|
+
break;
|
|
80444
|
+
}
|
|
80445
|
+
if (failures.length === 0)
|
|
80446
|
+
return "";
|
|
80447
|
+
return failures.map((f) => ` - ${f.logicalId} (${f.type}): ${f.reason}`).join("\n");
|
|
80448
|
+
}
|
|
80415
80449
|
async function executeUpdateChangeSet(cfnClient, stackName, template, parameters) {
|
|
80416
80450
|
const logger = getLogger();
|
|
80417
80451
|
const changeSetName = `cdkd-phase2-${Date.now()}`;
|
|
@@ -80593,7 +80627,7 @@ function reorderArgs(argv) {
|
|
|
80593
80627
|
}
|
|
80594
80628
|
async function main() {
|
|
80595
80629
|
const program = new Command18();
|
|
80596
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.91.
|
|
80630
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.91.4");
|
|
80597
80631
|
program.addCommand(createBootstrapCommand());
|
|
80598
80632
|
program.addCommand(createSynthCommand());
|
|
80599
80633
|
program.addCommand(createListCommand());
|