@go-to-k/cdkd 0.17.1 → 0.18.1
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/README.md +68 -14
- package/dist/cli.js +461 -209
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.18.1.tgz +0 -0
- package/dist/index.js +158 -118
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.17.1.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -447,7 +447,7 @@ var init_aws_clients = __esm({
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
// src/cli/index.ts
|
|
450
|
-
import { Command as
|
|
450
|
+
import { Command as Command13 } from "commander";
|
|
451
451
|
|
|
452
452
|
// src/cli/commands/bootstrap.ts
|
|
453
453
|
import { Command, Option as Option2 } from "commander";
|
|
@@ -537,10 +537,122 @@ var destroyOptions = [
|
|
|
537
537
|
)
|
|
538
538
|
];
|
|
539
539
|
|
|
540
|
+
// src/provisioning/resource-name.ts
|
|
541
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
542
|
+
import { createHash } from "node:crypto";
|
|
543
|
+
var stackNameStore = new AsyncLocalStorage();
|
|
544
|
+
function withStackName(stackName, fn) {
|
|
545
|
+
return stackNameStore.run(stackName, fn);
|
|
546
|
+
}
|
|
547
|
+
function getCurrentStackName() {
|
|
548
|
+
return stackNameStore.getStore();
|
|
549
|
+
}
|
|
550
|
+
function generateResourceName(name, options) {
|
|
551
|
+
const { maxLength, lowercase = false, allowedPattern = /[^a-zA-Z0-9-]/g } = options;
|
|
552
|
+
const currentStackName = stackNameStore.getStore();
|
|
553
|
+
const fullName = currentStackName ? `${currentStackName}-${name}` : name;
|
|
554
|
+
let sanitized = lowercase ? fullName.toLowerCase() : fullName;
|
|
555
|
+
sanitized = sanitized.replace(allowedPattern, "-");
|
|
556
|
+
sanitized = sanitized.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
557
|
+
if (sanitized.length <= maxLength) {
|
|
558
|
+
return sanitized;
|
|
559
|
+
}
|
|
560
|
+
const hash = createHash("sha256").update(fullName).digest("hex").substring(0, 8);
|
|
561
|
+
const maxPrefixLength = maxLength - hash.length - 1;
|
|
562
|
+
const prefix = sanitized.substring(0, maxPrefixLength).replace(/-+$/, "");
|
|
563
|
+
return `${prefix}-${hash}`;
|
|
564
|
+
}
|
|
565
|
+
var FALLBACK_NAME_RULES = {
|
|
566
|
+
"AWS::S3::Bucket": { nameProperty: "BucketName", options: { maxLength: 63, lowercase: true } },
|
|
567
|
+
"AWS::SQS::Queue": { nameProperty: "QueueName", options: { maxLength: 80 } },
|
|
568
|
+
"AWS::SNS::Topic": { nameProperty: "TopicName", options: { maxLength: 256 } },
|
|
569
|
+
"AWS::Lambda::Function": { nameProperty: "FunctionName", options: { maxLength: 64 } },
|
|
570
|
+
"AWS::Lambda::LayerVersion": { nameProperty: "LayerName", options: { maxLength: 64 } },
|
|
571
|
+
"AWS::IAM::Role": { nameProperty: "RoleName", options: { maxLength: 64 } },
|
|
572
|
+
"AWS::IAM::Policy": { nameProperty: "PolicyName", options: { maxLength: 64 } },
|
|
573
|
+
"AWS::IAM::User": { nameProperty: "UserName", options: { maxLength: 64 } },
|
|
574
|
+
"AWS::IAM::Group": { nameProperty: "GroupName", options: { maxLength: 128 } },
|
|
575
|
+
"AWS::IAM::InstanceProfile": {
|
|
576
|
+
nameProperty: "InstanceProfileName",
|
|
577
|
+
options: { maxLength: 128 }
|
|
578
|
+
},
|
|
579
|
+
"AWS::DynamoDB::Table": { nameProperty: "TableName", options: { maxLength: 255 } },
|
|
580
|
+
"AWS::ECR::Repository": {
|
|
581
|
+
nameProperty: "RepositoryName",
|
|
582
|
+
options: { maxLength: 256, lowercase: true }
|
|
583
|
+
},
|
|
584
|
+
"AWS::ECS::Cluster": { nameProperty: "ClusterName", options: { maxLength: 255 } },
|
|
585
|
+
"AWS::ECS::Service": { nameProperty: "ServiceName", options: { maxLength: 255 } },
|
|
586
|
+
"AWS::Logs::LogGroup": { nameProperty: "LogGroupName", options: { maxLength: 512 } },
|
|
587
|
+
"AWS::CloudWatch::Alarm": { nameProperty: "AlarmName", options: { maxLength: 256 } },
|
|
588
|
+
"AWS::Events::Rule": { nameProperty: "Name", options: { maxLength: 64 } },
|
|
589
|
+
"AWS::Events::EventBus": { nameProperty: "Name", options: { maxLength: 256 } },
|
|
590
|
+
"AWS::Kinesis::Stream": { nameProperty: "Name", options: { maxLength: 128 } },
|
|
591
|
+
"AWS::StepFunctions::StateMachine": {
|
|
592
|
+
nameProperty: "StateMachineName",
|
|
593
|
+
options: { maxLength: 80 }
|
|
594
|
+
},
|
|
595
|
+
"AWS::SecretsManager::Secret": {
|
|
596
|
+
nameProperty: "Name",
|
|
597
|
+
options: { maxLength: 512, allowedPattern: /[^a-zA-Z0-9-/_]/g }
|
|
598
|
+
},
|
|
599
|
+
"AWS::SSM::Parameter": { nameProperty: "Name", options: { maxLength: 2048 } },
|
|
600
|
+
"AWS::Cognito::UserPool": { nameProperty: "UserPoolName", options: { maxLength: 128 } },
|
|
601
|
+
"AWS::ElastiCache::SubnetGroup": {
|
|
602
|
+
nameProperty: "CacheSubnetGroupName",
|
|
603
|
+
options: { maxLength: 255, lowercase: true }
|
|
604
|
+
},
|
|
605
|
+
"AWS::ElastiCache::CacheCluster": {
|
|
606
|
+
nameProperty: "ClusterName",
|
|
607
|
+
options: { maxLength: 40, lowercase: true }
|
|
608
|
+
},
|
|
609
|
+
"AWS::RDS::DBSubnetGroup": {
|
|
610
|
+
nameProperty: "DBSubnetGroupName",
|
|
611
|
+
options: { maxLength: 255, lowercase: true }
|
|
612
|
+
},
|
|
613
|
+
"AWS::RDS::DBCluster": {
|
|
614
|
+
nameProperty: "DBClusterIdentifier",
|
|
615
|
+
options: { maxLength: 63, lowercase: true }
|
|
616
|
+
},
|
|
617
|
+
"AWS::RDS::DBInstance": {
|
|
618
|
+
nameProperty: "DBInstanceIdentifier",
|
|
619
|
+
options: { maxLength: 63, lowercase: true }
|
|
620
|
+
},
|
|
621
|
+
"AWS::ElasticLoadBalancingV2::LoadBalancer": {
|
|
622
|
+
nameProperty: "Name",
|
|
623
|
+
options: { maxLength: 32 }
|
|
624
|
+
},
|
|
625
|
+
"AWS::ElasticLoadBalancingV2::TargetGroup": {
|
|
626
|
+
nameProperty: "Name",
|
|
627
|
+
options: { maxLength: 32 }
|
|
628
|
+
},
|
|
629
|
+
"AWS::WAFv2::WebACL": { nameProperty: "Name", options: { maxLength: 128 } },
|
|
630
|
+
"AWS::CodeBuild::Project": { nameProperty: "Name", options: { maxLength: 255 } },
|
|
631
|
+
"AWS::S3Express::DirectoryBucket": {
|
|
632
|
+
nameProperty: "BucketName",
|
|
633
|
+
options: { maxLength: 63, lowercase: true }
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
function applyDefaultNameForFallback(logicalId, resourceType, properties) {
|
|
637
|
+
const rule = FALLBACK_NAME_RULES[resourceType];
|
|
638
|
+
if (!rule)
|
|
639
|
+
return properties;
|
|
640
|
+
if (properties[rule.nameProperty])
|
|
641
|
+
return properties;
|
|
642
|
+
const generatedName = generateResourceName(logicalId, rule.options);
|
|
643
|
+
return {
|
|
644
|
+
...properties,
|
|
645
|
+
[rule.nameProperty]: generatedName
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
540
649
|
// src/utils/live-renderer.ts
|
|
541
650
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
542
651
|
var FRAME_INTERVAL_MS = 80;
|
|
543
652
|
var ESC = "\x1B[";
|
|
653
|
+
function scopedKey(id, stackName) {
|
|
654
|
+
return stackName ? `${stackName}:${id}` : id;
|
|
655
|
+
}
|
|
544
656
|
var LiveRenderer = class {
|
|
545
657
|
constructor(stream = process.stdout) {
|
|
546
658
|
this.stream = stream;
|
|
@@ -594,12 +706,14 @@ var LiveRenderer = class {
|
|
|
594
706
|
this.active = false;
|
|
595
707
|
}
|
|
596
708
|
addTask(id, label) {
|
|
597
|
-
|
|
709
|
+
const stackName = getCurrentStackName();
|
|
710
|
+
this.tasks.set(scopedKey(id, stackName), { label, startedAt: Date.now(), stackName });
|
|
598
711
|
if (this.active)
|
|
599
712
|
this.draw();
|
|
600
713
|
}
|
|
601
714
|
removeTask(id) {
|
|
602
|
-
|
|
715
|
+
const stackName = getCurrentStackName();
|
|
716
|
+
if (!this.tasks.delete(scopedKey(id, stackName)))
|
|
603
717
|
return;
|
|
604
718
|
if (this.active)
|
|
605
719
|
this.draw();
|
|
@@ -635,11 +749,16 @@ var LiveRenderer = class {
|
|
|
635
749
|
return;
|
|
636
750
|
const frame = SPINNER_FRAMES[this.spinnerIndex % SPINNER_FRAMES.length];
|
|
637
751
|
this.spinnerIndex++;
|
|
752
|
+
const distinctStacks = /* @__PURE__ */ new Set();
|
|
753
|
+
for (const task of this.tasks.values())
|
|
754
|
+
distinctStacks.add(task.stackName);
|
|
755
|
+
const showStackPrefix = distinctStacks.size > 1;
|
|
638
756
|
const cols = this.stream.columns ?? 80;
|
|
639
757
|
const lines = [];
|
|
640
758
|
for (const task of this.tasks.values()) {
|
|
641
759
|
const elapsed = ((Date.now() - task.startedAt) / 1e3).toFixed(1);
|
|
642
|
-
const
|
|
760
|
+
const prefix = showStackPrefix && task.stackName ? `[${task.stackName}] ` : "";
|
|
761
|
+
const raw = ` ${frame} ${prefix}${task.label} (${elapsed}s)`;
|
|
643
762
|
lines.push(this.truncate(raw, cols));
|
|
644
763
|
}
|
|
645
764
|
this.stream.write(lines.join("\n") + "\n");
|
|
@@ -672,6 +791,24 @@ function getLiveRenderer() {
|
|
|
672
791
|
return globalRenderer;
|
|
673
792
|
}
|
|
674
793
|
|
|
794
|
+
// src/utils/stack-context.ts
|
|
795
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
796
|
+
var outputBufferStore = new AsyncLocalStorage2();
|
|
797
|
+
async function runStackBuffered(fn) {
|
|
798
|
+
const buffer = { lines: [] };
|
|
799
|
+
return outputBufferStore.run(buffer, async () => {
|
|
800
|
+
try {
|
|
801
|
+
const result = await fn();
|
|
802
|
+
return { ok: true, result, lines: buffer.lines };
|
|
803
|
+
} catch (error) {
|
|
804
|
+
return { ok: false, error, lines: buffer.lines };
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
function getCurrentStackOutputBuffer() {
|
|
809
|
+
return outputBufferStore.getStore();
|
|
810
|
+
}
|
|
811
|
+
|
|
675
812
|
// src/utils/logger.ts
|
|
676
813
|
var colors = {
|
|
677
814
|
reset: "\x1B[0m",
|
|
@@ -726,28 +863,48 @@ var ConsoleLogger = class {
|
|
|
726
863
|
}
|
|
727
864
|
return `${message}${formattedArgs}`;
|
|
728
865
|
}
|
|
866
|
+
/**
|
|
867
|
+
* Route a formatted log line. When a per-stack output buffer is active in
|
|
868
|
+
* the current async context (parallel multi-stack deploy), capture the
|
|
869
|
+
* line into the buffer so it can be flushed as one atomic block when the
|
|
870
|
+
* stack finishes. Otherwise fall through to the live renderer / console
|
|
871
|
+
* as before.
|
|
872
|
+
*/
|
|
873
|
+
emit(level, formatted) {
|
|
874
|
+
const buffer = getCurrentStackOutputBuffer();
|
|
875
|
+
if (buffer) {
|
|
876
|
+
buffer.lines.push(formatted);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
getLiveRenderer().printAbove(() => {
|
|
880
|
+
if (level === "error")
|
|
881
|
+
console.error(formatted);
|
|
882
|
+
else if (level === "warn")
|
|
883
|
+
console.warn(formatted);
|
|
884
|
+
else if (level === "info")
|
|
885
|
+
console.info(formatted);
|
|
886
|
+
else
|
|
887
|
+
console.debug(formatted);
|
|
888
|
+
});
|
|
889
|
+
}
|
|
729
890
|
debug(message, ...args) {
|
|
730
891
|
if (this.shouldLog("debug")) {
|
|
731
|
-
|
|
732
|
-
getLiveRenderer().printAbove(() => console.debug(formatted));
|
|
892
|
+
this.emit("debug", this.formatMessage("debug", message, ...args));
|
|
733
893
|
}
|
|
734
894
|
}
|
|
735
895
|
info(message, ...args) {
|
|
736
896
|
if (this.shouldLog("info")) {
|
|
737
|
-
|
|
738
|
-
getLiveRenderer().printAbove(() => console.info(formatted));
|
|
897
|
+
this.emit("info", this.formatMessage("info", message, ...args));
|
|
739
898
|
}
|
|
740
899
|
}
|
|
741
900
|
warn(message, ...args) {
|
|
742
901
|
if (this.shouldLog("warn")) {
|
|
743
|
-
|
|
744
|
-
getLiveRenderer().printAbove(() => console.warn(formatted));
|
|
902
|
+
this.emit("warn", this.formatMessage("warn", message, ...args));
|
|
745
903
|
}
|
|
746
904
|
}
|
|
747
905
|
error(message, ...args) {
|
|
748
906
|
if (this.shouldLog("error")) {
|
|
749
|
-
|
|
750
|
-
getLiveRenderer().printAbove(() => console.error(formatted));
|
|
907
|
+
this.emit("error", this.formatMessage("error", message, ...args));
|
|
751
908
|
}
|
|
752
909
|
}
|
|
753
910
|
/**
|
|
@@ -3488,7 +3645,7 @@ var S3StateBackend = class {
|
|
|
3488
3645
|
*
|
|
3489
3646
|
* Returns true for either layout: the new region-scoped key, or the legacy
|
|
3490
3647
|
* key when its embedded `region` matches the requested region. This lets
|
|
3491
|
-
* `cdkd state
|
|
3648
|
+
* `cdkd state orphan <stack> --region X` and `cdkd destroy <stack>` see legacy
|
|
3492
3649
|
* state without forcing a write-through migration first.
|
|
3493
3650
|
*/
|
|
3494
3651
|
async stateExists(stackName, region) {
|
|
@@ -7765,112 +7922,6 @@ import {
|
|
|
7765
7922
|
} from "@aws-sdk/client-iam";
|
|
7766
7923
|
init_aws_clients();
|
|
7767
7924
|
|
|
7768
|
-
// src/provisioning/resource-name.ts
|
|
7769
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7770
|
-
import { createHash } from "node:crypto";
|
|
7771
|
-
var stackNameStore = new AsyncLocalStorage();
|
|
7772
|
-
function withStackName(stackName, fn) {
|
|
7773
|
-
return stackNameStore.run(stackName, fn);
|
|
7774
|
-
}
|
|
7775
|
-
function generateResourceName(name, options) {
|
|
7776
|
-
const { maxLength, lowercase = false, allowedPattern = /[^a-zA-Z0-9-]/g } = options;
|
|
7777
|
-
const currentStackName = stackNameStore.getStore();
|
|
7778
|
-
const fullName = currentStackName ? `${currentStackName}-${name}` : name;
|
|
7779
|
-
let sanitized = lowercase ? fullName.toLowerCase() : fullName;
|
|
7780
|
-
sanitized = sanitized.replace(allowedPattern, "-");
|
|
7781
|
-
sanitized = sanitized.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
7782
|
-
if (sanitized.length <= maxLength) {
|
|
7783
|
-
return sanitized;
|
|
7784
|
-
}
|
|
7785
|
-
const hash = createHash("sha256").update(fullName).digest("hex").substring(0, 8);
|
|
7786
|
-
const maxPrefixLength = maxLength - hash.length - 1;
|
|
7787
|
-
const prefix = sanitized.substring(0, maxPrefixLength).replace(/-+$/, "");
|
|
7788
|
-
return `${prefix}-${hash}`;
|
|
7789
|
-
}
|
|
7790
|
-
var FALLBACK_NAME_RULES = {
|
|
7791
|
-
"AWS::S3::Bucket": { nameProperty: "BucketName", options: { maxLength: 63, lowercase: true } },
|
|
7792
|
-
"AWS::SQS::Queue": { nameProperty: "QueueName", options: { maxLength: 80 } },
|
|
7793
|
-
"AWS::SNS::Topic": { nameProperty: "TopicName", options: { maxLength: 256 } },
|
|
7794
|
-
"AWS::Lambda::Function": { nameProperty: "FunctionName", options: { maxLength: 64 } },
|
|
7795
|
-
"AWS::Lambda::LayerVersion": { nameProperty: "LayerName", options: { maxLength: 64 } },
|
|
7796
|
-
"AWS::IAM::Role": { nameProperty: "RoleName", options: { maxLength: 64 } },
|
|
7797
|
-
"AWS::IAM::Policy": { nameProperty: "PolicyName", options: { maxLength: 64 } },
|
|
7798
|
-
"AWS::IAM::User": { nameProperty: "UserName", options: { maxLength: 64 } },
|
|
7799
|
-
"AWS::IAM::Group": { nameProperty: "GroupName", options: { maxLength: 128 } },
|
|
7800
|
-
"AWS::IAM::InstanceProfile": {
|
|
7801
|
-
nameProperty: "InstanceProfileName",
|
|
7802
|
-
options: { maxLength: 128 }
|
|
7803
|
-
},
|
|
7804
|
-
"AWS::DynamoDB::Table": { nameProperty: "TableName", options: { maxLength: 255 } },
|
|
7805
|
-
"AWS::ECR::Repository": {
|
|
7806
|
-
nameProperty: "RepositoryName",
|
|
7807
|
-
options: { maxLength: 256, lowercase: true }
|
|
7808
|
-
},
|
|
7809
|
-
"AWS::ECS::Cluster": { nameProperty: "ClusterName", options: { maxLength: 255 } },
|
|
7810
|
-
"AWS::ECS::Service": { nameProperty: "ServiceName", options: { maxLength: 255 } },
|
|
7811
|
-
"AWS::Logs::LogGroup": { nameProperty: "LogGroupName", options: { maxLength: 512 } },
|
|
7812
|
-
"AWS::CloudWatch::Alarm": { nameProperty: "AlarmName", options: { maxLength: 256 } },
|
|
7813
|
-
"AWS::Events::Rule": { nameProperty: "Name", options: { maxLength: 64 } },
|
|
7814
|
-
"AWS::Events::EventBus": { nameProperty: "Name", options: { maxLength: 256 } },
|
|
7815
|
-
"AWS::Kinesis::Stream": { nameProperty: "Name", options: { maxLength: 128 } },
|
|
7816
|
-
"AWS::StepFunctions::StateMachine": {
|
|
7817
|
-
nameProperty: "StateMachineName",
|
|
7818
|
-
options: { maxLength: 80 }
|
|
7819
|
-
},
|
|
7820
|
-
"AWS::SecretsManager::Secret": {
|
|
7821
|
-
nameProperty: "Name",
|
|
7822
|
-
options: { maxLength: 512, allowedPattern: /[^a-zA-Z0-9-/_]/g }
|
|
7823
|
-
},
|
|
7824
|
-
"AWS::SSM::Parameter": { nameProperty: "Name", options: { maxLength: 2048 } },
|
|
7825
|
-
"AWS::Cognito::UserPool": { nameProperty: "UserPoolName", options: { maxLength: 128 } },
|
|
7826
|
-
"AWS::ElastiCache::SubnetGroup": {
|
|
7827
|
-
nameProperty: "CacheSubnetGroupName",
|
|
7828
|
-
options: { maxLength: 255, lowercase: true }
|
|
7829
|
-
},
|
|
7830
|
-
"AWS::ElastiCache::CacheCluster": {
|
|
7831
|
-
nameProperty: "ClusterName",
|
|
7832
|
-
options: { maxLength: 40, lowercase: true }
|
|
7833
|
-
},
|
|
7834
|
-
"AWS::RDS::DBSubnetGroup": {
|
|
7835
|
-
nameProperty: "DBSubnetGroupName",
|
|
7836
|
-
options: { maxLength: 255, lowercase: true }
|
|
7837
|
-
},
|
|
7838
|
-
"AWS::RDS::DBCluster": {
|
|
7839
|
-
nameProperty: "DBClusterIdentifier",
|
|
7840
|
-
options: { maxLength: 63, lowercase: true }
|
|
7841
|
-
},
|
|
7842
|
-
"AWS::RDS::DBInstance": {
|
|
7843
|
-
nameProperty: "DBInstanceIdentifier",
|
|
7844
|
-
options: { maxLength: 63, lowercase: true }
|
|
7845
|
-
},
|
|
7846
|
-
"AWS::ElasticLoadBalancingV2::LoadBalancer": {
|
|
7847
|
-
nameProperty: "Name",
|
|
7848
|
-
options: { maxLength: 32 }
|
|
7849
|
-
},
|
|
7850
|
-
"AWS::ElasticLoadBalancingV2::TargetGroup": {
|
|
7851
|
-
nameProperty: "Name",
|
|
7852
|
-
options: { maxLength: 32 }
|
|
7853
|
-
},
|
|
7854
|
-
"AWS::WAFv2::WebACL": { nameProperty: "Name", options: { maxLength: 128 } },
|
|
7855
|
-
"AWS::CodeBuild::Project": { nameProperty: "Name", options: { maxLength: 255 } },
|
|
7856
|
-
"AWS::S3Express::DirectoryBucket": {
|
|
7857
|
-
nameProperty: "BucketName",
|
|
7858
|
-
options: { maxLength: 63, lowercase: true }
|
|
7859
|
-
}
|
|
7860
|
-
};
|
|
7861
|
-
function applyDefaultNameForFallback(logicalId, resourceType, properties) {
|
|
7862
|
-
const rule = FALLBACK_NAME_RULES[resourceType];
|
|
7863
|
-
if (!rule)
|
|
7864
|
-
return properties;
|
|
7865
|
-
if (properties[rule.nameProperty])
|
|
7866
|
-
return properties;
|
|
7867
|
-
const generatedName = generateResourceName(logicalId, rule.options);
|
|
7868
|
-
return {
|
|
7869
|
-
...properties,
|
|
7870
|
-
[rule.nameProperty]: generatedName
|
|
7871
|
-
};
|
|
7872
|
-
}
|
|
7873
|
-
|
|
7874
7925
|
// src/provisioning/import-helpers.ts
|
|
7875
7926
|
function readNameProperty(input, propertyName) {
|
|
7876
7927
|
const value = input.properties?.[propertyName];
|
|
@@ -29998,6 +30049,68 @@ async function deployCommand(stacks, options) {
|
|
|
29998
30049
|
}
|
|
29999
30050
|
const summary = workGraph.summary();
|
|
30000
30051
|
logger.debug(`Work graph: ${summary["asset-publish"]} asset(s), ${summary["stack"]} stack(s)`);
|
|
30052
|
+
const bufferStackOutput = targetStacks.length > 1;
|
|
30053
|
+
const runStack = async (stackInfo) => {
|
|
30054
|
+
const stackRegion = stackInfo.region || baseRegion;
|
|
30055
|
+
logger.info(
|
|
30056
|
+
`
|
|
30057
|
+
Deploying stack: ${stackInfo.stackName}${stackRegion !== baseRegion ? ` (region: ${stackRegion})` : ""}`
|
|
30058
|
+
);
|
|
30059
|
+
switchRegion(stackRegion);
|
|
30060
|
+
const stackAwsClients = new AwsClients({
|
|
30061
|
+
region: stackRegion,
|
|
30062
|
+
...options.profile && { profile: options.profile }
|
|
30063
|
+
});
|
|
30064
|
+
setAwsClients(stackAwsClients);
|
|
30065
|
+
const stateS3Client = new AwsClients({
|
|
30066
|
+
region: baseRegion,
|
|
30067
|
+
...options.profile && { profile: options.profile }
|
|
30068
|
+
});
|
|
30069
|
+
const stackStateBackend = new S3StateBackend(stateS3Client.s3, stateConfig, {
|
|
30070
|
+
region: baseRegion,
|
|
30071
|
+
...options.profile && { profile: options.profile }
|
|
30072
|
+
});
|
|
30073
|
+
const stackLockManager = new LockManager(stateS3Client.s3, stateConfig);
|
|
30074
|
+
const stackProviderRegistry = new ProviderRegistry();
|
|
30075
|
+
registerAllProviders(stackProviderRegistry);
|
|
30076
|
+
stackProviderRegistry.setCustomResourceResponseBucket(stateBucket, baseRegion);
|
|
30077
|
+
const stackDeployEngine = new DeployEngine(
|
|
30078
|
+
stackStateBackend,
|
|
30079
|
+
stackLockManager,
|
|
30080
|
+
dagBuilder,
|
|
30081
|
+
diffCalculator,
|
|
30082
|
+
stackProviderRegistry,
|
|
30083
|
+
{
|
|
30084
|
+
concurrency: options.concurrency,
|
|
30085
|
+
dryRun: options.dryRun,
|
|
30086
|
+
noRollback: !options.rollback
|
|
30087
|
+
},
|
|
30088
|
+
stackRegion
|
|
30089
|
+
);
|
|
30090
|
+
try {
|
|
30091
|
+
const deployResult = await stackDeployEngine.deploy(
|
|
30092
|
+
stackInfo.stackName,
|
|
30093
|
+
stackInfo.template
|
|
30094
|
+
);
|
|
30095
|
+
logger.info("\nDeployment Summary:");
|
|
30096
|
+
logger.info(` Stack: ${deployResult.stackName}`);
|
|
30097
|
+
logger.info(` Created: ${deployResult.created}`);
|
|
30098
|
+
logger.info(` Updated: ${deployResult.updated}`);
|
|
30099
|
+
logger.info(` Deleted: ${deployResult.deleted}`);
|
|
30100
|
+
logger.info(` Unchanged: ${deployResult.unchanged}`);
|
|
30101
|
+
logger.info(` Duration: ${(deployResult.durationMs / 1e3).toFixed(2)}s`);
|
|
30102
|
+
if (options.dryRun) {
|
|
30103
|
+
logger.info("\n\u2713 Dry run completed - no actual changes made");
|
|
30104
|
+
} else {
|
|
30105
|
+
logger.info("\n\u2713 Deployment completed successfully");
|
|
30106
|
+
}
|
|
30107
|
+
} finally {
|
|
30108
|
+
stackAwsClients.destroy();
|
|
30109
|
+
stateS3Client.destroy();
|
|
30110
|
+
switchRegion(baseRegion);
|
|
30111
|
+
setAwsClients(awsClients);
|
|
30112
|
+
}
|
|
30113
|
+
};
|
|
30001
30114
|
await workGraph.execute(
|
|
30002
30115
|
{
|
|
30003
30116
|
"asset-build": options.imageBuildConcurrency,
|
|
@@ -30009,65 +30122,16 @@ async function deployCommand(stacks, options) {
|
|
|
30009
30122
|
await assetPublisher.executeNode(node);
|
|
30010
30123
|
} else {
|
|
30011
30124
|
const { stack: stackInfo } = node.data;
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
|
|
30015
|
-
Deploying stack: ${stackInfo.stackName}${stackRegion !== baseRegion ? ` (region: ${stackRegion})` : ""}`
|
|
30016
|
-
);
|
|
30017
|
-
switchRegion(stackRegion);
|
|
30018
|
-
const stackAwsClients = new AwsClients({
|
|
30019
|
-
region: stackRegion,
|
|
30020
|
-
...options.profile && { profile: options.profile }
|
|
30021
|
-
});
|
|
30022
|
-
setAwsClients(stackAwsClients);
|
|
30023
|
-
const stateS3Client = new AwsClients({
|
|
30024
|
-
region: baseRegion,
|
|
30025
|
-
...options.profile && { profile: options.profile }
|
|
30026
|
-
});
|
|
30027
|
-
const stackStateBackend = new S3StateBackend(stateS3Client.s3, stateConfig, {
|
|
30028
|
-
region: baseRegion,
|
|
30029
|
-
...options.profile && { profile: options.profile }
|
|
30030
|
-
});
|
|
30031
|
-
const stackLockManager = new LockManager(stateS3Client.s3, stateConfig);
|
|
30032
|
-
const stackProviderRegistry = new ProviderRegistry();
|
|
30033
|
-
registerAllProviders(stackProviderRegistry);
|
|
30034
|
-
stackProviderRegistry.setCustomResourceResponseBucket(stateBucket, baseRegion);
|
|
30035
|
-
const stackDeployEngine = new DeployEngine(
|
|
30036
|
-
stackStateBackend,
|
|
30037
|
-
stackLockManager,
|
|
30038
|
-
dagBuilder,
|
|
30039
|
-
diffCalculator,
|
|
30040
|
-
stackProviderRegistry,
|
|
30041
|
-
{
|
|
30042
|
-
concurrency: options.concurrency,
|
|
30043
|
-
dryRun: options.dryRun,
|
|
30044
|
-
noRollback: !options.rollback
|
|
30045
|
-
},
|
|
30046
|
-
stackRegion
|
|
30047
|
-
);
|
|
30048
|
-
try {
|
|
30049
|
-
const deployResult = await stackDeployEngine.deploy(
|
|
30050
|
-
stackInfo.stackName,
|
|
30051
|
-
stackInfo.template
|
|
30052
|
-
);
|
|
30053
|
-
logger.info("\nDeployment Summary:");
|
|
30054
|
-
logger.info(` Stack: ${deployResult.stackName}`);
|
|
30055
|
-
logger.info(` Created: ${deployResult.created}`);
|
|
30056
|
-
logger.info(` Updated: ${deployResult.updated}`);
|
|
30057
|
-
logger.info(` Deleted: ${deployResult.deleted}`);
|
|
30058
|
-
logger.info(` Unchanged: ${deployResult.unchanged}`);
|
|
30059
|
-
logger.info(` Duration: ${(deployResult.durationMs / 1e3).toFixed(2)}s`);
|
|
30060
|
-
if (options.dryRun) {
|
|
30061
|
-
logger.info("\n\u2713 Dry run completed - no actual changes made");
|
|
30062
|
-
} else {
|
|
30063
|
-
logger.info("\n\u2713 Deployment completed successfully");
|
|
30064
|
-
}
|
|
30065
|
-
} finally {
|
|
30066
|
-
stackAwsClients.destroy();
|
|
30067
|
-
stateS3Client.destroy();
|
|
30068
|
-
switchRegion(baseRegion);
|
|
30069
|
-
setAwsClients(awsClients);
|
|
30125
|
+
if (!bufferStackOutput) {
|
|
30126
|
+
await runStack(stackInfo);
|
|
30127
|
+
return;
|
|
30070
30128
|
}
|
|
30129
|
+
const outcome = await runStackBuffered(() => runStack(stackInfo));
|
|
30130
|
+
if (outcome.lines.length > 0) {
|
|
30131
|
+
process.stdout.write(outcome.lines.join("\n") + "\n");
|
|
30132
|
+
}
|
|
30133
|
+
if (!outcome.ok)
|
|
30134
|
+
throw outcome.error;
|
|
30071
30135
|
}
|
|
30072
30136
|
}
|
|
30073
30137
|
);
|
|
@@ -30630,7 +30694,7 @@ Preparing to destroy stack: ${stackName}`);
|
|
|
30630
30694
|
} else {
|
|
30631
30695
|
const regions = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
30632
30696
|
throw new Error(
|
|
30633
|
-
`Stack '${stackName}' has state in multiple regions: ${regions}. Use 'cdkd state
|
|
30697
|
+
`Stack '${stackName}' has state in multiple regions: ${regions}. Use 'cdkd state orphan ${stackName} --region <region>' to remove cdkd's record for one region, or run destroy from a CDK app whose env.region matches one of them.`
|
|
30634
30698
|
);
|
|
30635
30699
|
}
|
|
30636
30700
|
const stateResult = await stateBackend.getState(stackName, stackTargetRegion);
|
|
@@ -30670,8 +30734,192 @@ function createDestroyCommand() {
|
|
|
30670
30734
|
return cmd;
|
|
30671
30735
|
}
|
|
30672
30736
|
|
|
30737
|
+
// src/cli/commands/orphan.ts
|
|
30738
|
+
import * as readline2 from "node:readline/promises";
|
|
30739
|
+
import { Command as Command7 } from "commander";
|
|
30740
|
+
init_aws_clients();
|
|
30741
|
+
async function orphanCommand(stackArgs, options) {
|
|
30742
|
+
const logger = getLogger();
|
|
30743
|
+
if (options.verbose)
|
|
30744
|
+
logger.setLevel("debug");
|
|
30745
|
+
warnIfDeprecatedRegion(options);
|
|
30746
|
+
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
30747
|
+
const stateBucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
30748
|
+
logger.info("Starting stack orphan...");
|
|
30749
|
+
logger.debug("Options:", options);
|
|
30750
|
+
if (options.region) {
|
|
30751
|
+
process.env["AWS_REGION"] = options.region;
|
|
30752
|
+
process.env["AWS_DEFAULT_REGION"] = options.region;
|
|
30753
|
+
}
|
|
30754
|
+
const awsClients = new AwsClients({
|
|
30755
|
+
...options.region && { region: options.region },
|
|
30756
|
+
...options.profile && { profile: options.profile }
|
|
30757
|
+
});
|
|
30758
|
+
setAwsClients(awsClients);
|
|
30759
|
+
try {
|
|
30760
|
+
const stateConfig = {
|
|
30761
|
+
bucket: stateBucket,
|
|
30762
|
+
prefix: options.statePrefix
|
|
30763
|
+
};
|
|
30764
|
+
const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
|
|
30765
|
+
...options.region && { region: options.region },
|
|
30766
|
+
...options.profile && { profile: options.profile }
|
|
30767
|
+
});
|
|
30768
|
+
await stateBackend.verifyBucketExists();
|
|
30769
|
+
const lockManager = new LockManager(awsClients.s3, stateConfig);
|
|
30770
|
+
const appCmd = options.app || resolveApp();
|
|
30771
|
+
let appStacks = [];
|
|
30772
|
+
if (appCmd) {
|
|
30773
|
+
try {
|
|
30774
|
+
const synthesizer = new Synthesizer();
|
|
30775
|
+
const context = parseContextOptions(options.context);
|
|
30776
|
+
const result = await synthesizer.synthesize({
|
|
30777
|
+
app: appCmd,
|
|
30778
|
+
output: options.output || "cdk.out",
|
|
30779
|
+
...Object.keys(context).length > 0 && { context }
|
|
30780
|
+
});
|
|
30781
|
+
appStacks = result.stacks.map((s) => ({
|
|
30782
|
+
stackName: s.stackName,
|
|
30783
|
+
displayName: s.displayName,
|
|
30784
|
+
...s.region && { region: s.region }
|
|
30785
|
+
}));
|
|
30786
|
+
} catch {
|
|
30787
|
+
logger.debug("Could not synthesize app, falling back to state-based stack list");
|
|
30788
|
+
}
|
|
30789
|
+
}
|
|
30790
|
+
const allStateRefs = await stateBackend.listStacks();
|
|
30791
|
+
let candidateStacks;
|
|
30792
|
+
if (appStacks.length > 0) {
|
|
30793
|
+
const stateNames = new Set(allStateRefs.map((r) => r.stackName));
|
|
30794
|
+
candidateStacks = appStacks.filter((s) => stateNames.has(s.stackName));
|
|
30795
|
+
} else if (stackArgs.length > 0 || options.stack || options.all) {
|
|
30796
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30797
|
+
candidateStacks = [];
|
|
30798
|
+
for (const ref of allStateRefs) {
|
|
30799
|
+
if (seen.has(ref.stackName))
|
|
30800
|
+
continue;
|
|
30801
|
+
seen.add(ref.stackName);
|
|
30802
|
+
candidateStacks.push({ stackName: ref.stackName });
|
|
30803
|
+
}
|
|
30804
|
+
} else {
|
|
30805
|
+
throw new Error(
|
|
30806
|
+
"Could not determine which stacks belong to this app. Specify stack names explicitly, use --all, or ensure --app / cdk.json is configured."
|
|
30807
|
+
);
|
|
30808
|
+
}
|
|
30809
|
+
const stackPatterns = stackArgs.length > 0 ? stackArgs : options.stack ? [options.stack] : [];
|
|
30810
|
+
let stackNames;
|
|
30811
|
+
if (options.all) {
|
|
30812
|
+
stackNames = candidateStacks.map((s) => s.stackName);
|
|
30813
|
+
} else if (stackPatterns.length > 0) {
|
|
30814
|
+
stackNames = matchStacks(candidateStacks, stackPatterns).map((s) => s.stackName);
|
|
30815
|
+
} else if (candidateStacks.length === 1) {
|
|
30816
|
+
stackNames = candidateStacks.map((s) => s.stackName);
|
|
30817
|
+
} else if (candidateStacks.length === 0) {
|
|
30818
|
+
logger.info("No stacks found in state");
|
|
30819
|
+
return;
|
|
30820
|
+
} else {
|
|
30821
|
+
throw new Error(
|
|
30822
|
+
`Multiple stacks found: ${candidateStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`
|
|
30823
|
+
);
|
|
30824
|
+
}
|
|
30825
|
+
if (stackNames.length === 0) {
|
|
30826
|
+
logger.info("No matching stacks found in state");
|
|
30827
|
+
return;
|
|
30828
|
+
}
|
|
30829
|
+
logger.info(`Found ${stackNames.length} stack(s) to orphan: ${stackNames.join(", ")}`);
|
|
30830
|
+
const stateRefsByName = /* @__PURE__ */ new Map();
|
|
30831
|
+
for (const ref of allStateRefs) {
|
|
30832
|
+
const arr = stateRefsByName.get(ref.stackName) ?? [];
|
|
30833
|
+
arr.push(ref);
|
|
30834
|
+
stateRefsByName.set(ref.stackName, arr);
|
|
30835
|
+
}
|
|
30836
|
+
const skipConfirmation = options.yes || options.force;
|
|
30837
|
+
for (const stackName of stackNames) {
|
|
30838
|
+
const refs = stateRefsByName.get(stackName) ?? [];
|
|
30839
|
+
if (refs.length === 0) {
|
|
30840
|
+
logger.info(`No state found for stack: ${stackName}, skipping`);
|
|
30841
|
+
continue;
|
|
30842
|
+
}
|
|
30843
|
+
const targets = options.stackRegion ? refs.filter((r) => r.region === options.stackRegion) : refs;
|
|
30844
|
+
if (targets.length === 0) {
|
|
30845
|
+
const seen = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
30846
|
+
throw new Error(
|
|
30847
|
+
`No state found for stack '${stackName}' in region '${options.stackRegion}'. Available regions: ${seen}.`
|
|
30848
|
+
);
|
|
30849
|
+
}
|
|
30850
|
+
if (!options.force) {
|
|
30851
|
+
for (const target of targets) {
|
|
30852
|
+
const locked = await lockManager.isLocked(stackName, target.region);
|
|
30853
|
+
if (locked) {
|
|
30854
|
+
const where = target.region ?? "(legacy)";
|
|
30855
|
+
throw new Error(
|
|
30856
|
+
`Stack '${stackName}' (${where}) is locked. Run 'cdkd force-unlock ${stackName}${target.region ? ` --stack-region ${target.region}` : ""}' first, or pass --force to orphan anyway.`
|
|
30857
|
+
);
|
|
30858
|
+
}
|
|
30859
|
+
}
|
|
30860
|
+
}
|
|
30861
|
+
if (!skipConfirmation) {
|
|
30862
|
+
const targetList = targets.map((t) => t.region ? `${stackName} (${t.region})` : stackName).join(", ");
|
|
30863
|
+
process.stdout.write(
|
|
30864
|
+
`
|
|
30865
|
+
WARNING: This removes cdkd's state record for [${targetList}] only. AWS resources will NOT be deleted.
|
|
30866
|
+
Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
|
|
30867
|
+
|
|
30868
|
+
`
|
|
30869
|
+
);
|
|
30870
|
+
const rl = readline2.createInterface({
|
|
30871
|
+
input: process.stdin,
|
|
30872
|
+
output: process.stdout
|
|
30873
|
+
});
|
|
30874
|
+
const answer = await rl.question(
|
|
30875
|
+
`Orphan state for ${targetList} from s3://${stateBucket}/${options.statePrefix}/? (y/N): `
|
|
30876
|
+
);
|
|
30877
|
+
rl.close();
|
|
30878
|
+
const trimmed = answer.trim().toLowerCase();
|
|
30879
|
+
if (trimmed !== "y" && trimmed !== "yes") {
|
|
30880
|
+
logger.info(`Cancelled orphan of stack: ${stackName}`);
|
|
30881
|
+
continue;
|
|
30882
|
+
}
|
|
30883
|
+
}
|
|
30884
|
+
for (const target of targets) {
|
|
30885
|
+
if (target.region) {
|
|
30886
|
+
await stateBackend.deleteState(stackName, target.region);
|
|
30887
|
+
await lockManager.forceReleaseLock(stackName, target.region);
|
|
30888
|
+
} else {
|
|
30889
|
+
await lockManager.forceReleaseLock(stackName, void 0);
|
|
30890
|
+
}
|
|
30891
|
+
const label = target.region ? `${stackName} (${target.region})` : stackName;
|
|
30892
|
+
logger.info(`\u2713 Orphaned state for stack: ${label}`);
|
|
30893
|
+
}
|
|
30894
|
+
}
|
|
30895
|
+
} finally {
|
|
30896
|
+
awsClients.destroy();
|
|
30897
|
+
}
|
|
30898
|
+
}
|
|
30899
|
+
function createOrphanCommand() {
|
|
30900
|
+
const cmd = new Command7("orphan").description(
|
|
30901
|
+
"Remove cdkd's state record for one or more stacks (does NOT delete AWS resources). Synth-driven; for the CDK-app-free version use 'cdkd state orphan'."
|
|
30902
|
+
).argument(
|
|
30903
|
+
"[stacks...]",
|
|
30904
|
+
"Stack name(s) to orphan. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*')."
|
|
30905
|
+
).option("--all", "Orphan all stacks in the current app", false).option(
|
|
30906
|
+
"--stack-region <region>",
|
|
30907
|
+
"Region of the stack record to operate on. Required when the same stack name has state in multiple regions."
|
|
30908
|
+
).action(withErrorHandling(orphanCommand));
|
|
30909
|
+
[
|
|
30910
|
+
...commonOptions,
|
|
30911
|
+
...appOptions,
|
|
30912
|
+
...stateOptions,
|
|
30913
|
+
...stackOptions,
|
|
30914
|
+
...destroyOptions,
|
|
30915
|
+
...contextOptions
|
|
30916
|
+
].forEach((opt) => cmd.addOption(opt));
|
|
30917
|
+
cmd.addOption(deprecatedRegionOption);
|
|
30918
|
+
return cmd;
|
|
30919
|
+
}
|
|
30920
|
+
|
|
30673
30921
|
// src/cli/commands/publish-assets.ts
|
|
30674
|
-
import { Option as Option3, Command as
|
|
30922
|
+
import { Option as Option3, Command as Command8 } from "commander";
|
|
30675
30923
|
async function publishAssetsCommand(options) {
|
|
30676
30924
|
const logger = getLogger();
|
|
30677
30925
|
if (options.verbose) {
|
|
@@ -30690,7 +30938,7 @@ async function publishAssetsCommand(options) {
|
|
|
30690
30938
|
logger.info("\u2705 Asset publishing complete");
|
|
30691
30939
|
}
|
|
30692
30940
|
function createPublishAssetsCommand() {
|
|
30693
|
-
const cmd = new
|
|
30941
|
+
const cmd = new Command8("publish-assets").description("Publish assets to S3/ECR from asset manifest").requiredOption("--path <path>", "Path to asset manifest file or directory").addOption(
|
|
30694
30942
|
new Option3(
|
|
30695
30943
|
"--asset-publish-concurrency <number>",
|
|
30696
30944
|
"Maximum concurrent asset publish operations"
|
|
@@ -30704,7 +30952,7 @@ function createPublishAssetsCommand() {
|
|
|
30704
30952
|
}
|
|
30705
30953
|
|
|
30706
30954
|
// src/cli/commands/force-unlock.ts
|
|
30707
|
-
import { Command as
|
|
30955
|
+
import { Command as Command9, Option as Option4 } from "commander";
|
|
30708
30956
|
init_aws_clients();
|
|
30709
30957
|
async function forceUnlockCommand(stackArgs, options) {
|
|
30710
30958
|
const logger = getLogger();
|
|
@@ -30764,7 +31012,7 @@ async function forceUnlockCommand(stackArgs, options) {
|
|
|
30764
31012
|
}
|
|
30765
31013
|
}
|
|
30766
31014
|
function createForceUnlockCommand() {
|
|
30767
|
-
const cmd = new
|
|
31015
|
+
const cmd = new Command9("force-unlock").description("Force-release a stale lock on a stack").argument("[stacks...]", "Stack name(s) to unlock").addOption(
|
|
30768
31016
|
new Option4(
|
|
30769
31017
|
"--stack-region <region>",
|
|
30770
31018
|
"Stack region whose lock to release (use when the same stack name has locks in multiple regions). Defaults to all regions where the stack has state."
|
|
@@ -30776,8 +31024,8 @@ function createForceUnlockCommand() {
|
|
|
30776
31024
|
}
|
|
30777
31025
|
|
|
30778
31026
|
// src/cli/commands/state.ts
|
|
30779
|
-
import * as
|
|
30780
|
-
import { Command as
|
|
31027
|
+
import * as readline4 from "node:readline/promises";
|
|
31028
|
+
import { Command as Command11, Option as Option5 } from "commander";
|
|
30781
31029
|
import {
|
|
30782
31030
|
GetBucketLocationCommand as GetBucketLocationCommand2,
|
|
30783
31031
|
GetObjectCommand as GetObjectCommand4,
|
|
@@ -30786,8 +31034,8 @@ import {
|
|
|
30786
31034
|
init_aws_clients();
|
|
30787
31035
|
|
|
30788
31036
|
// src/cli/commands/state-migrate.ts
|
|
30789
|
-
import * as
|
|
30790
|
-
import { Command as
|
|
31037
|
+
import * as readline3 from "node:readline/promises";
|
|
31038
|
+
import { Command as Command10 } from "commander";
|
|
30791
31039
|
import {
|
|
30792
31040
|
CopyObjectCommand,
|
|
30793
31041
|
CreateBucketCommand as CreateBucketCommand4,
|
|
@@ -31061,7 +31309,7 @@ async function emptyBucketAllVersions(s3, bucket) {
|
|
|
31061
31309
|
} while (keyMarker || versionIdMarker);
|
|
31062
31310
|
}
|
|
31063
31311
|
async function confirmPrompt(prompt) {
|
|
31064
|
-
const rl =
|
|
31312
|
+
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
31065
31313
|
try {
|
|
31066
31314
|
const ans = await rl.question(`${prompt} [y/N] `);
|
|
31067
31315
|
return /^y(es)?$/i.test(ans.trim());
|
|
@@ -31070,7 +31318,7 @@ async function confirmPrompt(prompt) {
|
|
|
31070
31318
|
}
|
|
31071
31319
|
}
|
|
31072
31320
|
function createStateMigrateCommand() {
|
|
31073
|
-
const cmd = new
|
|
31321
|
+
const cmd = new Command10("migrate").description(
|
|
31074
31322
|
"Migrate state from the legacy region-suffixed bucket (cdkd-state-{account}-{region}) to the new region-free default (cdkd-state-{account}). Source bucket is kept by default; pass --remove-legacy to delete it after a successful migration."
|
|
31075
31323
|
).option(
|
|
31076
31324
|
"--region <region>",
|
|
@@ -31228,7 +31476,7 @@ async function stateListCommand(options) {
|
|
|
31228
31476
|
}
|
|
31229
31477
|
}
|
|
31230
31478
|
function createStateListCommand() {
|
|
31231
|
-
const cmd = new
|
|
31479
|
+
const cmd = new Command11("list").alias("ls").description("List stacks registered in the cdkd state bucket").option("-l, --long", "Show resource count, last-modified time, and lock status", false).option("--json", "Output as JSON", false).action(withErrorHandling(stateListCommand));
|
|
31232
31480
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31233
31481
|
cmd.addOption(deprecatedRegionOption);
|
|
31234
31482
|
return cmd;
|
|
@@ -31332,7 +31580,7 @@ function formatLockSummary(lockInfo) {
|
|
|
31332
31580
|
return `locked by ${lockInfo.owner}${opStr}, ${expiresStr}`;
|
|
31333
31581
|
}
|
|
31334
31582
|
function createStateResourcesCommand() {
|
|
31335
|
-
const cmd = new
|
|
31583
|
+
const cmd = new Command11("resources").description("List resources recorded in a stack's state").argument("<stack>", "Stack name (physical CloudFormation name)").option("-l, --long", "Include dependencies and attributes per resource", false).option("--json", "Output as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(stateResourcesCommand));
|
|
31336
31584
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31337
31585
|
cmd.addOption(deprecatedRegionOption);
|
|
31338
31586
|
return cmd;
|
|
@@ -31420,17 +31668,17 @@ async function stateShowCommand(stackName, options) {
|
|
|
31420
31668
|
}
|
|
31421
31669
|
}
|
|
31422
31670
|
function createStateShowCommand() {
|
|
31423
|
-
const cmd = new
|
|
31671
|
+
const cmd = new Command11("show").description("Show the full cdkd state record for a stack (metadata, outputs, resources)").argument("<stack>", "Stack name (physical CloudFormation name)").option("--json", "Output the raw state and lock as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(stateShowCommand));
|
|
31424
31672
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31425
31673
|
cmd.addOption(deprecatedRegionOption);
|
|
31426
31674
|
return cmd;
|
|
31427
31675
|
}
|
|
31428
|
-
async function
|
|
31676
|
+
async function stateOrphanCommand(stackArgs, options) {
|
|
31429
31677
|
const logger = getLogger();
|
|
31430
31678
|
if (options.verbose)
|
|
31431
31679
|
logger.setLevel("debug");
|
|
31432
31680
|
if (stackArgs.length === 0) {
|
|
31433
|
-
throw new Error("Stack name is required. Usage: cdkd state
|
|
31681
|
+
throw new Error("Stack name is required. Usage: cdkd state orphan <stack> [<stack>...]");
|
|
31434
31682
|
}
|
|
31435
31683
|
const setup = await setupStateBackend(options);
|
|
31436
31684
|
try {
|
|
@@ -31468,7 +31716,7 @@ Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
|
|
|
31468
31716
|
|
|
31469
31717
|
`
|
|
31470
31718
|
);
|
|
31471
|
-
const rl =
|
|
31719
|
+
const rl = readline4.createInterface({
|
|
31472
31720
|
input: process.stdin,
|
|
31473
31721
|
output: process.stdout
|
|
31474
31722
|
});
|
|
@@ -31502,8 +31750,10 @@ function stackRegionOption() {
|
|
|
31502
31750
|
"Region of the stack record to operate on. Required when the same stack name has state in multiple regions."
|
|
31503
31751
|
);
|
|
31504
31752
|
}
|
|
31505
|
-
function
|
|
31506
|
-
const cmd = new
|
|
31753
|
+
function createStateOrphanCommand() {
|
|
31754
|
+
const cmd = new Command11("orphan").description(
|
|
31755
|
+
"Orphan one or more stacks from cdkd state (removes the state record; does NOT delete AWS resources)"
|
|
31756
|
+
).argument("<stacks...>", "Stack name(s) to orphan from state").option("-f, --force", "Skip confirmation and remove even if the stack is locked", false).addOption(stackRegionOption()).action(withErrorHandling(stateOrphanCommand));
|
|
31507
31757
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31508
31758
|
cmd.addOption(deprecatedRegionOption);
|
|
31509
31759
|
return cmd;
|
|
@@ -31553,7 +31803,7 @@ WARNING: This destroys ${stackNames.length} stack(s) and removes their state rec
|
|
|
31553
31803
|
`);
|
|
31554
31804
|
}
|
|
31555
31805
|
process.stdout.write("\n");
|
|
31556
|
-
const rl =
|
|
31806
|
+
const rl = readline4.createInterface({
|
|
31557
31807
|
input: process.stdin,
|
|
31558
31808
|
output: process.stdout
|
|
31559
31809
|
});
|
|
@@ -31628,8 +31878,8 @@ Preparing to destroy stack: ${stackName}${ref.region ? ` (${ref.region})` : ""}`
|
|
|
31628
31878
|
}
|
|
31629
31879
|
}
|
|
31630
31880
|
function createStateDestroyCommand() {
|
|
31631
|
-
const cmd = new
|
|
31632
|
-
"Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state
|
|
31881
|
+
const cmd = new Command11("destroy").description(
|
|
31882
|
+
"Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'."
|
|
31633
31883
|
).argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).addOption(stackRegionOption()).addHelpText(
|
|
31634
31884
|
"after",
|
|
31635
31885
|
[
|
|
@@ -31641,7 +31891,7 @@ function createStateDestroyCommand() {
|
|
|
31641
31891
|
" cdkd state destroy MyStack --state-bucket cdkd-state-test",
|
|
31642
31892
|
" cdkd state destroy MyStack --stack-region us-west-2",
|
|
31643
31893
|
"",
|
|
31644
|
-
"For removing only the state record (keeping AWS resources intact), use 'cdkd state
|
|
31894
|
+
"For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'."
|
|
31645
31895
|
].join("\n")
|
|
31646
31896
|
).action(withErrorHandling(stateDestroyCommand));
|
|
31647
31897
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
@@ -31760,19 +32010,19 @@ async function stateInfoCommand(options) {
|
|
|
31760
32010
|
}
|
|
31761
32011
|
}
|
|
31762
32012
|
function createStateInfoCommand() {
|
|
31763
|
-
const cmd = new
|
|
32013
|
+
const cmd = new Command11("info").description(
|
|
31764
32014
|
"Show cdkd state bucket info (bucket name, region, source, schema version, stack count)"
|
|
31765
32015
|
).option("--json", "Output as JSON", false).action(withErrorHandling(stateInfoCommand));
|
|
31766
32016
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31767
32017
|
return cmd;
|
|
31768
32018
|
}
|
|
31769
32019
|
function createStateCommand() {
|
|
31770
|
-
const cmd = new
|
|
32020
|
+
const cmd = new Command11("state").description("Manage cdkd state stored in S3");
|
|
31771
32021
|
cmd.addCommand(createStateInfoCommand());
|
|
31772
32022
|
cmd.addCommand(createStateListCommand());
|
|
31773
32023
|
cmd.addCommand(createStateResourcesCommand());
|
|
31774
32024
|
cmd.addCommand(createStateShowCommand());
|
|
31775
|
-
cmd.addCommand(
|
|
32025
|
+
cmd.addCommand(createStateOrphanCommand());
|
|
31776
32026
|
cmd.addCommand(createStateDestroyCommand());
|
|
31777
32027
|
cmd.addCommand(createStateMigrateCommand());
|
|
31778
32028
|
return cmd;
|
|
@@ -31780,8 +32030,8 @@ function createStateCommand() {
|
|
|
31780
32030
|
|
|
31781
32031
|
// src/cli/commands/import.ts
|
|
31782
32032
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
31783
|
-
import * as
|
|
31784
|
-
import { Command as
|
|
32033
|
+
import * as readline5 from "node:readline/promises";
|
|
32034
|
+
import { Command as Command12 } from "commander";
|
|
31785
32035
|
init_aws_clients();
|
|
31786
32036
|
async function importCommand(stackArg, options) {
|
|
31787
32037
|
const logger = getLogger();
|
|
@@ -32077,7 +32327,7 @@ function formatOutcome(outcome) {
|
|
|
32077
32327
|
}
|
|
32078
32328
|
}
|
|
32079
32329
|
async function confirmPrompt2(prompt) {
|
|
32080
|
-
const rl =
|
|
32330
|
+
const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
|
|
32081
32331
|
try {
|
|
32082
32332
|
const ans = await rl.question(`${prompt} [y/N] `);
|
|
32083
32333
|
return /^y(es)?$/i.test(ans.trim());
|
|
@@ -32086,7 +32336,7 @@ async function confirmPrompt2(prompt) {
|
|
|
32086
32336
|
}
|
|
32087
32337
|
}
|
|
32088
32338
|
function createImportCommand() {
|
|
32089
|
-
const cmd = new
|
|
32339
|
+
const cmd = new Command12("import").description(
|
|
32090
32340
|
"Adopt already-deployed AWS resources into cdkd state. Reads the CDK app to find logical IDs, resource types, and dependencies; uses the aws:cdk:path tag (or explicit --resource overrides) to find each resource in AWS."
|
|
32091
32341
|
).argument(
|
|
32092
32342
|
"[stack]",
|
|
@@ -32122,6 +32372,7 @@ var SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
|
32122
32372
|
"deploy",
|
|
32123
32373
|
"diff",
|
|
32124
32374
|
"destroy",
|
|
32375
|
+
"orphan",
|
|
32125
32376
|
"import",
|
|
32126
32377
|
"publish-assets",
|
|
32127
32378
|
"force-unlock",
|
|
@@ -32138,14 +32389,15 @@ function reorderArgs(argv) {
|
|
|
32138
32389
|
return [...prefix, ...cmdAndAfter, ...beforeCmd];
|
|
32139
32390
|
}
|
|
32140
32391
|
async function main() {
|
|
32141
|
-
const program = new
|
|
32142
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
32392
|
+
const program = new Command13();
|
|
32393
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.18.1");
|
|
32143
32394
|
program.addCommand(createBootstrapCommand());
|
|
32144
32395
|
program.addCommand(createSynthCommand());
|
|
32145
32396
|
program.addCommand(createListCommand());
|
|
32146
32397
|
program.addCommand(createDeployCommand());
|
|
32147
32398
|
program.addCommand(createDiffCommand());
|
|
32148
32399
|
program.addCommand(createDestroyCommand());
|
|
32400
|
+
program.addCommand(createOrphanCommand());
|
|
32149
32401
|
program.addCommand(createImportCommand());
|
|
32150
32402
|
program.addCommand(createPublishAssetsCommand());
|
|
32151
32403
|
program.addCommand(createForceUnlockCommand());
|