@go-to-k/cdkd 0.193.0 → 0.194.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { _ as withSkipPrefix, a as runDockerStreaming, c as getLogger, d as getLiveRenderer, f as PATTERN_B_NAME_PROPERTIES, g as generateResourceNameWithFallback, h as generateResourceName, i as runDockerForeground, n as formatDockerLoginError, p as PATTERN_B_RESOURCE_TYPES, r as getDockerCmd, u as runStackBuffered, v as withStackName } from "./docker-cmd-iDMcWcre.js";
3
- import { A as S3StateBackend, B as resolveCaptureObservedState, C as assertRegionMatch, D as DagBuilder, E as DiffCalculator, F as buildDockerImage, G as CFN_TEMPLATE_BODY_LIMIT, H as resolveStateBucketWithDefault, I as Synthesizer, J as findLargeInlineResources, K as CFN_TEMPLATE_URL_LIMIT, L as getDefaultStateBucketName, M as AssetPublisher, N as stringifyValue, O as TemplateParser, P as WorkGraph, Q as resolveBucketRegion, R as getLegacyStateBucketName, S as CloudControlProvider, T as applyRoleArnIfSet, U as resolveStateBucketWithDefaultAndSource, V as resolveSkipPrefix, W as warnDeprecatedNoPrefixCliFlag, X as AssemblyReader, Y as uploadCfnTemplate, _ as matchesCdkPath, a as withRetry, at as LocalStartServiceError, b as ProviderRegistry, bt as withErrorHandling, c as bold, ct as NestedStackChildDirectDestroyError, d as green, dt as ResourceTimeoutError, et as CdkdError, f as red, ft as ResourceUpdateNotSupportedError, g as CDK_PATH_TAG, h as collectInlinePolicyNamesManagedBySiblings, i as withResourceDeadline, it as LocalMigrateError, j as shouldRetainResource, k as LockManager, l as cyan, lt as PartialFailureError, m as IAMRoleProvider, mt as StackTerminationProtectionError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as IMPLICIT_DELETE_DEPENDENCIES, p as yellow, pt as StackHasActiveImportsError, q as MIGRATE_TMP_PREFIX, r as DeployEngine, rt as LocalInvokeBuildError$1, s as formatResourceLine, st as MissingCdkCliError, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as gray, ut as ProvisioningError, v as normalizeAwsTagsToCfn, w as IntrinsicFunctionResolver, x as findActionableSilentDrops, y as resolveExplicitPhysicalId, yt as normalizeAwsError, z as resolveApp } from "./deploy-engine-CaeIu1xD.js";
3
+ import { A as S3StateBackend, B as resolveCaptureObservedState, C as assertRegionMatch, D as DagBuilder, E as DiffCalculator, F as buildDockerImage, G as CFN_TEMPLATE_BODY_LIMIT, H as resolveStateBucketWithDefault, I as Synthesizer, J as findLargeInlineResources, K as CFN_TEMPLATE_URL_LIMIT, L as getDefaultStateBucketName, M as AssetPublisher, N as stringifyValue, O as TemplateParser, P as WorkGraph, Q as resolveBucketRegion, R as getLegacyStateBucketName, S as CloudControlProvider, T as applyRoleArnIfSet, U as resolveStateBucketWithDefaultAndSource, V as resolveSkipPrefix, W as warnDeprecatedNoPrefixCliFlag, X as AssemblyReader, Y as uploadCfnTemplate, _ as matchesCdkPath, a as withRetry, at as LocalStartServiceError, b as ProviderRegistry, bt as withErrorHandling, c as bold, ct as NestedStackChildDirectDestroyError, d as green, dt as ResourceTimeoutError, et as CdkdError, f as red, ft as ResourceUpdateNotSupportedError, g as CDK_PATH_TAG, h as collectInlinePolicyNamesManagedBySiblings, i as withResourceDeadline, it as LocalMigrateError, j as shouldRetainResource, k as LockManager, l as cyan, lt as PartialFailureError, m as IAMRoleProvider, mt as StackTerminationProtectionError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, o as IMPLICIT_DELETE_DEPENDENCIES, p as yellow, pt as StackHasActiveImportsError, q as MIGRATE_TMP_PREFIX, r as DeployEngine, rt as LocalInvokeBuildError$1, s as formatResourceLine, st as MissingCdkCliError, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as gray, ut as ProvisioningError, v as normalizeAwsTagsToCfn, w as IntrinsicFunctionResolver, x as findActionableSilentDrops, y as resolveExplicitPhysicalId, yt as normalizeAwsError, z as resolveApp } from "./deploy-engine-BDmJX4ss.js";
4
4
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-B15NAPbL.js";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { randomBytes, randomUUID } from "node:crypto";
@@ -28,7 +28,7 @@ import * as path from "node:path";
28
28
  import { dirname, isAbsolute, join, resolve } from "node:path";
29
29
  import { execFile, spawn } from "node:child_process";
30
30
  import { tmpdir } from "node:os";
31
- import { AssociateVPCWithHostedZoneCommand, ChangeResourceRecordSetsCommand, ChangeTagsForResourceCommand, CreateHostedZoneCommand, CreateQueryLoggingConfigCommand, DeleteHostedZoneCommand, DeleteQueryLoggingConfigCommand, DisassociateVPCFromHostedZoneCommand, GetHostedZoneCommand, ListHostedZonesByNameCommand, ListHostedZonesCommand, ListQueryLoggingConfigsCommand, ListResourceRecordSetsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$6, Route53Client, UpdateHostedZoneCommentCommand } from "@aws-sdk/client-route-53";
31
+ import { AssociateVPCWithHostedZoneCommand, ChangeResourceRecordSetsCommand, ChangeTagsForResourceCommand, CreateHostedZoneCommand, CreateQueryLoggingConfigCommand, DeleteHostedZoneCommand, DeleteQueryLoggingConfigCommand, DisassociateVPCFromHostedZoneCommand, GetHostedZoneCommand, ListHostedZonesByNameCommand, ListHostedZonesCommand, ListQueryLoggingConfigsCommand, ListResourceRecordSetsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$6, Route53Client, UpdateHostedZoneCommentCommand, UpdateHostedZoneFeaturesCommand } from "@aws-sdk/client-route-53";
32
32
  import { AddTagsCommand, CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, DeleteListenerCommand, DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DescribeListenersCommand, DescribeLoadBalancerAttributesCommand, DescribeLoadBalancersCommand, DescribeTagsCommand, DescribeTargetGroupsCommand, ElasticLoadBalancingV2Client, ModifyListenerCommand, ModifyLoadBalancerAttributesCommand, ModifyTargetGroupCommand, RemoveTagsCommand, SetIpAddressTypeCommand, SetSecurityGroupsCommand, SetSubnetsCommand } from "@aws-sdk/client-elastic-load-balancing-v2";
33
33
  import { CreateAliasCommand, CreateKeyCommand, DeleteAliasCommand, DescribeKeyCommand, DisableKeyCommand, DisableKeyRotationCommand, EnableKeyCommand, EnableKeyRotationCommand, GetKeyPolicyCommand, GetKeyRotationStatusCommand, KMSClient, ListAliasesCommand, ListKeysCommand, ListResourceTagsCommand, NotFoundException as NotFoundException$2, PutKeyPolicyCommand, ScheduleKeyDeletionCommand, TagResourceCommand as TagResourceCommand$8, UntagResourceCommand as UntagResourceCommand$8, UpdateAliasCommand, UpdateKeyDescriptionCommand } from "@aws-sdk/client-kms";
34
34
  import { CreateRepositoryCommand, DeleteLifecyclePolicyCommand, DeleteRepositoryCommand, DeleteRepositoryPolicyCommand, DescribeRepositoriesCommand, ECRClient, GetAuthorizationTokenCommand, GetLifecyclePolicyCommand, LifecyclePolicyNotFoundException, ListTagsForResourceCommand as ListTagsForResourceCommand$7, PutImageScanningConfigurationCommand, PutImageTagMutabilityCommand, PutLifecyclePolicyCommand, RepositoryNotFoundException, SetRepositoryPolicyCommand, TagResourceCommand as TagResourceCommand$9 } from "@aws-sdk/client-ecr";
@@ -22650,7 +22650,8 @@ var Route53Provider = class {
22650
22650
  "HostedZoneConfig",
22651
22651
  "HostedZoneTags",
22652
22652
  "VPCs",
22653
- "QueryLoggingConfig"
22653
+ "QueryLoggingConfig",
22654
+ "HostedZoneFeatures"
22654
22655
  ])], ["AWS::Route53::RecordSet", new Set([
22655
22656
  "HostedZoneId",
22656
22657
  "HostedZoneName",
@@ -22681,9 +22682,9 @@ var Route53Provider = class {
22681
22682
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
22682
22683
  }
22683
22684
  }
22684
- async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
22685
+ async update(logicalId, physicalId, resourceType, properties, previousProperties) {
22685
22686
  switch (resourceType) {
22686
- case "AWS::Route53::HostedZone": return this.updateHostedZone(logicalId, physicalId, resourceType, properties);
22687
+ case "AWS::Route53::HostedZone": return this.updateHostedZone(logicalId, physicalId, resourceType, properties, previousProperties);
22687
22688
  case "AWS::Route53::RecordSet": return this.updateRecordSet(logicalId, physicalId, resourceType, properties);
22688
22689
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
22689
22690
  }
@@ -22737,6 +22738,22 @@ var Route53Provider = class {
22737
22738
  }
22738
22739
  await this.applyHostedZoneTags(zoneId, properties, logicalId);
22739
22740
  await this.applyQueryLoggingConfig(zoneId, properties, logicalId);
22741
+ if (properties["HostedZoneFeatures"]?.["AcceleratedRecoveryStatus"] === "ENABLED") try {
22742
+ await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
22743
+ HostedZoneId: zoneId,
22744
+ EnableAcceleratedRecovery: true
22745
+ }));
22746
+ } catch (uhfError) {
22747
+ this.logger.error(`UpdateHostedZoneFeatures failed for ${zoneId} after CreateHostedZone — rolling back the hosted zone to keep deploy retry idempotent`);
22748
+ try {
22749
+ await this.deleteQueryLoggingConfigForZone(zoneId, logicalId);
22750
+ await this.getClient().send(new DeleteHostedZoneCommand({ Id: zoneId }));
22751
+ } catch (deleteError) {
22752
+ this.logger.warn(`Best-effort rollback DeleteHostedZone for ${zoneId} also failed: ${deleteError instanceof Error ? deleteError.message : String(deleteError)} — operator may need to clean up the orphan zone`);
22753
+ }
22754
+ const cause = uhfError instanceof Error ? uhfError : void 0;
22755
+ throw new ProvisioningError(`Failed to enable Accelerated Recovery on hosted zone ${logicalId} (${zoneId}): ${uhfError instanceof Error ? uhfError.message : String(uhfError)}`, resourceType, logicalId, zoneId, cause);
22756
+ }
22740
22757
  const nameServers = response.DelegationSet?.NameServers ?? [];
22741
22758
  this.logger.debug(`Successfully created hosted zone ${logicalId}: ${zoneId}`);
22742
22759
  return {
@@ -22752,7 +22769,7 @@ var Route53Provider = class {
22752
22769
  throw new ProvisioningError(`Failed to create hosted zone ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
22753
22770
  }
22754
22771
  }
22755
- async updateHostedZone(logicalId, physicalId, resourceType, properties) {
22772
+ async updateHostedZone(logicalId, physicalId, resourceType, properties, previousProperties) {
22756
22773
  this.logger.debug(`Updating Route 53 hosted zone ${logicalId}: ${physicalId}`);
22757
22774
  try {
22758
22775
  const comment = properties["HostedZoneConfig"]?.["Comment"] ?? "";
@@ -22763,6 +22780,12 @@ var Route53Provider = class {
22763
22780
  await this.applyHostedZoneTags(physicalId, properties, logicalId);
22764
22781
  await this.applyQueryLoggingConfig(physicalId, properties, logicalId);
22765
22782
  await this.syncVPCAssociations(physicalId, properties, logicalId);
22783
+ const prevEnabled = previousProperties["HostedZoneFeatures"]?.["AcceleratedRecoveryStatus"] === "ENABLED";
22784
+ const nextEnabled = properties["HostedZoneFeatures"]?.["AcceleratedRecoveryStatus"] === "ENABLED";
22785
+ if (prevEnabled !== nextEnabled) await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
22786
+ HostedZoneId: physicalId,
22787
+ EnableAcceleratedRecovery: nextEnabled
22788
+ }));
22766
22789
  const nameServers = (await this.getClient().send(new GetHostedZoneCommand({ Id: physicalId }))).DelegationSet?.NameServers ?? [];
22767
22790
  this.logger.debug(`Successfully updated hosted zone ${logicalId}`);
22768
22791
  return {
@@ -22782,6 +22805,7 @@ var Route53Provider = class {
22782
22805
  this.logger.debug(`Deleting Route 53 hosted zone ${logicalId}: ${physicalId}`);
22783
22806
  try {
22784
22807
  await this.deleteQueryLoggingConfigForZone(physicalId, logicalId);
22808
+ await this.ensureAcceleratedRecoveryDisabledForDelete(physicalId, logicalId);
22785
22809
  await this.getClient().send(new DeleteHostedZoneCommand({ Id: physicalId }));
22786
22810
  this.logger.debug(`Successfully deleted hosted zone ${logicalId}`);
22787
22811
  } catch (error) {
@@ -22790,10 +22814,86 @@ var Route53Provider = class {
22790
22814
  this.logger.debug(`Hosted zone ${physicalId} does not exist, skipping deletion`);
22791
22815
  return;
22792
22816
  }
22817
+ if (error instanceof ProvisioningError) throw error;
22793
22818
  const cause = error instanceof Error ? error : void 0;
22794
22819
  throw new ProvisioningError(`Failed to delete hosted zone ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
22795
22820
  }
22796
22821
  }
22822
+ /**
22823
+ * Pre-delete guard for `AWS::Route53::HostedZone:HostedZoneFeatures`.
22824
+ *
22825
+ * AWS rejects `DeleteHostedZone` while AcceleratedRecovery is anything
22826
+ * other than DISABLED (the feature uses an async control plane API —
22827
+ * `UpdateHostedZoneFeatures` — and AWS won't tear down a zone whose
22828
+ * feature state is still in flight). This helper:
22829
+ *
22830
+ * 1. Reads the current `HostedZone.Features.AcceleratedRecoveryStatus`.
22831
+ * DISABLED / undefined / NoSuchHostedZone → return early (nothing
22832
+ * to do, the delete will proceed normally or hit the existing
22833
+ * NoSuchHostedZone short-circuit).
22834
+ * 2. ENABLING / ENABLED → issue `UpdateHostedZoneFeatures(false)` then
22835
+ * poll `GetHostedZone` until the status settles to DISABLED.
22836
+ * 3. DISABLING → poll without re-issuing the toggle.
22837
+ * 4. *_FAILED / *_HOSTED_ZONE_LOCKED → surface the AWS error to the
22838
+ * operator (out of scope for cdkd to recover automatically).
22839
+ *
22840
+ * Poll budget: env-overridable timeout (default 10 min) + interval
22841
+ * (default 15s; tests override via env to keep runs fast). Failure to
22842
+ * settle within the budget throws — the operator can either re-run
22843
+ * `cdkd state destroy` (poll resets) or disable manually.
22844
+ */
22845
+ async ensureAcceleratedRecoveryDisabledForDelete(physicalId, logicalId) {
22846
+ const client = this.getClient();
22847
+ const pollIntervalMs = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_INTERVAL_MS"] ?? "15000", 10);
22848
+ const timeoutMs = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_TIMEOUT_MS"] ?? "600000", 10);
22849
+ const readStatus = async () => {
22850
+ try {
22851
+ return (await client.send(new GetHostedZoneCommand({ Id: physicalId }))).HostedZone?.Features?.AcceleratedRecoveryStatus;
22852
+ } catch (err) {
22853
+ if (err instanceof Error && err.name === "NoSuchHostedZone") return void 0;
22854
+ throw err;
22855
+ }
22856
+ };
22857
+ const deadline = Date.now() + timeoutMs;
22858
+ const TERMINAL_FAILED = new Set([
22859
+ "ENABLE_FAILED",
22860
+ "DISABLE_FAILED",
22861
+ "ENABLING_HOSTED_ZONE_LOCKED",
22862
+ "DISABLING_HOSTED_ZONE_LOCKED"
22863
+ ]);
22864
+ const waitFor = async (targets, label) => {
22865
+ while (Date.now() < deadline) {
22866
+ const status = await readStatus();
22867
+ if (status === void 0 || targets.has(status)) return status;
22868
+ if (TERMINAL_FAILED.has(status)) throw new ProvisioningError(`Cannot delete hosted zone ${logicalId} (${physicalId}): AcceleratedRecoveryStatus transitioned to '${status}' while waiting for ${label} — operator must resolve before destroy can proceed`, "AWS::Route53::HostedZone", logicalId, physicalId);
22869
+ this.logger.debug(`Polling AcceleratedRecoveryStatus for ${physicalId}: ${status} (waiting for ${label}, will re-poll in ~${pollIntervalMs}ms)`);
22870
+ const sliceEnd = Math.min(Date.now() + pollIntervalMs, deadline);
22871
+ while (Date.now() < sliceEnd) {
22872
+ const tick = Math.min(1e3, sliceEnd - Date.now());
22873
+ if (tick <= 0) break;
22874
+ await new Promise((resolve) => setTimeout(resolve, tick));
22875
+ }
22876
+ }
22877
+ throw new ProvisioningError(`Timed out after ${timeoutMs}ms waiting for AcceleratedRecoveryStatus to reach ${label} on hosted zone ${logicalId} (${physicalId}); re-run \`cdkd state destroy\` or disable manually via \`aws route53 update-hosted-zone-features --hosted-zone-id ${physicalId} --no-enable-accelerated-recovery\``, "AWS::Route53::HostedZone", logicalId, physicalId);
22878
+ };
22879
+ let current = await readStatus();
22880
+ if (current === void 0 || current === "DISABLED") return;
22881
+ if (TERMINAL_FAILED.has(current)) throw new ProvisioningError(`Cannot delete hosted zone ${logicalId} (${physicalId}): AcceleratedRecoveryStatus is '${current}' — operator must resolve before destroy can proceed`, "AWS::Route53::HostedZone", logicalId, physicalId);
22882
+ if (current === "ENABLING") {
22883
+ this.logger.debug(`Hosted zone ${physicalId} is ENABLING; waiting for it to settle before issuing disable`);
22884
+ current = await waitFor(new Set(["ENABLED", "DISABLED"]), "ENABLED or DISABLED");
22885
+ if (current === void 0 || current === "DISABLED") return;
22886
+ }
22887
+ if (current === "ENABLED") {
22888
+ this.logger.debug(`Hosted zone ${physicalId} is ENABLED; issuing UpdateHostedZoneFeatures(false) before delete`);
22889
+ await client.send(new UpdateHostedZoneFeaturesCommand({
22890
+ HostedZoneId: physicalId,
22891
+ EnableAcceleratedRecovery: false
22892
+ }));
22893
+ } else if (current === "DISABLING") this.logger.debug(`Hosted zone ${physicalId} AcceleratedRecovery is already DISABLING; waiting for settle`);
22894
+ const settled = await waitFor(new Set(["DISABLED"]), "DISABLED");
22895
+ this.logger.debug(`Hosted zone ${physicalId} AcceleratedRecoveryStatus settled to ${settled ?? "undefined (zone gone)"}`);
22896
+ }
22797
22897
  async getHostedZoneAttribute(physicalId, attributeName) {
22798
22898
  switch (attributeName) {
22799
22899
  case "Id": return physicalId;
@@ -23131,6 +23231,7 @@ var Route53Provider = class {
23131
23231
  if (resp.HostedZone.Config?.PrivateZone !== void 0) cfg["PrivateZone"] = resp.HostedZone.Config.PrivateZone;
23132
23232
  result["HostedZoneConfig"] = cfg;
23133
23233
  }
23234
+ if (resp.HostedZone.Features?.AcceleratedRecoveryStatus !== void 0) result["HostedZoneFeatures"] = { AcceleratedRecoveryStatus: resp.HostedZone.Features.AcceleratedRecoveryStatus };
23134
23235
  if (resp.HostedZone.Config?.PrivateZone === true) result["VPCs"] = (resp.VPCs ?? []).map((v) => {
23135
23236
  const out = {};
23136
23237
  if (v.VPCId !== void 0) out["VPCId"] = v.VPCId;
@@ -52451,7 +52552,7 @@ function reorderArgs(argv) {
52451
52552
  */
52452
52553
  async function main() {
52453
52554
  const program = new Command();
52454
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.193.0");
52555
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.194.0");
52455
52556
  program.addCommand(createBootstrapCommand());
52456
52557
  program.addCommand(createSynthCommand());
52457
52558
  program.addCommand(createListCommand());