@go-to-k/cdkd 0.171.0 → 0.172.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-BqNTKqFf.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-ZV67Rszk.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";
@@ -11,7 +11,7 @@ import { CreateTopicCommand, DeleteTopicCommand, GetSubscriptionAttributesComman
11
11
  import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand as GetPolicyCommand$1, LambdaClient, ListFunctionsCommand, ListLayersCommand, ListTagsCommand, PublishLayerVersionCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
12
12
  import { AssumeRoleCommand, GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
13
13
  import { AssociateRouteTableCommand, AttachInternetGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAvailabilityZonesCommand, DescribeInstanceAttributeCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DetachInternetGatewayCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, ReplaceNetworkAclAssociationCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
14
- import { CreateTableCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDBClient, ListTablesCommand, ListTagsOfResourceCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
14
+ import { CreateTableCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DynamoDBClient, ListTablesCommand, ListTagsOfResourceCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateContinuousBackupsCommand, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
15
15
  import { CloudFormationClient, CreateChangeSetCommand, DeleteChangeSetCommand, DeleteStackCommand, DescribeChangeSetCommand, DescribeStackEventsCommand, DescribeStackResourcesCommand, DescribeStacksCommand, DescribeTypeCommand, ExecuteChangeSetCommand, GetTemplateCommand, UpdateStackCommand, waitUntilChangeSetCreateComplete, waitUntilStackDeleteComplete, waitUntilStackImportComplete, waitUntilStackUpdateComplete } from "@aws-sdk/client-cloudformation";
16
16
  import { APIGatewayClient, CreateAuthorizerCommand, CreateDeploymentCommand, CreateResourceCommand, CreateStageCommand, DeleteAuthorizerCommand, DeleteDeploymentCommand, DeleteMethodCommand, DeleteResourceCommand, DeleteStageCommand, GetAccountCommand, GetAuthorizerCommand, GetDeploymentCommand, GetMethodCommand, GetResourceCommand, GetStageCommand, NotFoundException as NotFoundException$1, PutIntegrationCommand, PutIntegrationResponseCommand, PutMethodCommand, PutMethodResponseCommand, TagResourceCommand as TagResourceCommand$3, UntagResourceCommand as UntagResourceCommand$3, UpdateAccountCommand, UpdateAuthorizerCommand, UpdateMethodCommand, UpdateStageCommand } from "@aws-sdk/client-api-gateway";
17
17
  import { CreateEventBusCommand, DeleteEventBusCommand, DeleteRuleCommand, DescribeEventBusCommand, DescribeRuleCommand, EventBridgeClient, ListEventBusesCommand, ListRulesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$1, ListTargetsByRuleCommand, PutRuleCommand, PutTargetsCommand, RemoveTargetsCommand, ResourceNotFoundException as ResourceNotFoundException$2, TagResourceCommand as TagResourceCommand$4, UntagResourceCommand as UntagResourceCommand$4, UpdateEventBusCommand } from "@aws-sdk/client-eventbridge";
@@ -8697,7 +8697,9 @@ var DynamoDBTableProvider = class {
8697
8697
  "SSESpecification",
8698
8698
  "Tags",
8699
8699
  "DeletionProtectionEnabled",
8700
- "TableClass"
8700
+ "TableClass",
8701
+ "PointInTimeRecoverySpecification",
8702
+ "TimeToLiveSpecification"
8701
8703
  ])]]);
8702
8704
  constructor() {
8703
8705
  const awsClients = getAwsClients();
@@ -8713,6 +8715,7 @@ var DynamoDBTableProvider = class {
8713
8715
  const attributeDefinitions = properties["AttributeDefinitions"];
8714
8716
  if (!keySchema) throw new ProvisioningError(`KeySchema is required for DynamoDB table ${logicalId}`, resourceType, logicalId);
8715
8717
  if (!attributeDefinitions) throw new ProvisioningError(`AttributeDefinitions is required for DynamoDB table ${logicalId}`, resourceType, logicalId);
8718
+ let tableCreated = false;
8716
8719
  try {
8717
8720
  const billingMode = properties["BillingMode"] || "PROVISIONED";
8718
8721
  const createParams = {
@@ -8739,8 +8742,11 @@ var DynamoDBTableProvider = class {
8739
8742
  if (properties["DeletionProtectionEnabled"] !== void 0) createParams.DeletionProtectionEnabled = properties["DeletionProtectionEnabled"];
8740
8743
  if (properties["TableClass"]) createParams.TableClass = properties["TableClass"];
8741
8744
  await this.dynamoDBClient.send(new CreateTableCommand(createParams));
8745
+ tableCreated = true;
8742
8746
  this.logger.debug(`CreateTable initiated for ${tableName}, waiting for ACTIVE status`);
8743
8747
  const tableInfo = await this.waitForTableActive(tableName);
8748
+ await this.applyPointInTimeRecovery(tableName, properties["PointInTimeRecoverySpecification"]);
8749
+ await this.applyTimeToLive(tableName, properties["TimeToLiveSpecification"]);
8744
8750
  this.logger.debug(`Successfully created DynamoDB table ${logicalId}: ${tableName}`);
8745
8751
  return {
8746
8752
  physicalId: tableName,
@@ -8752,6 +8758,12 @@ var DynamoDBTableProvider = class {
8752
8758
  }
8753
8759
  };
8754
8760
  } catch (error) {
8761
+ if (tableCreated) try {
8762
+ await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
8763
+ this.logger.debug(`Rolled back partially-created DynamoDB table ${tableName}`);
8764
+ } catch (cleanupError) {
8765
+ this.logger.warn(`Failed to roll back partially-created DynamoDB table ${tableName}: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`);
8766
+ }
8755
8767
  if (error instanceof ProvisioningError) throw error;
8756
8768
  const cause = error instanceof Error ? error : void 0;
8757
8769
  throw new ProvisioningError(`Failed to create DynamoDB table ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, tableName, cause);
@@ -8769,6 +8781,8 @@ var DynamoDBTableProvider = class {
8769
8781
  try {
8770
8782
  const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
8771
8783
  if (table?.TableArn) await this.applyTagDiff(table.TableArn, previousProperties["Tags"], properties["Tags"]);
8784
+ if (JSON.stringify(properties["PointInTimeRecoverySpecification"]) !== JSON.stringify(previousProperties["PointInTimeRecoverySpecification"])) await this.applyPointInTimeRecovery(physicalId, properties["PointInTimeRecoverySpecification"], previousProperties["PointInTimeRecoverySpecification"]);
8785
+ if (JSON.stringify(properties["TimeToLiveSpecification"]) !== JSON.stringify(previousProperties["TimeToLiveSpecification"])) await this.applyTimeToLive(physicalId, properties["TimeToLiveSpecification"], previousProperties["TimeToLiveSpecification"]);
8772
8786
  return {
8773
8787
  physicalId,
8774
8788
  wasReplaced: false,
@@ -8852,6 +8866,97 @@ var DynamoDBTableProvider = class {
8852
8866
  }
8853
8867
  }
8854
8868
  /**
8869
+ * Apply the table's `PointInTimeRecoverySpecification` via the separate
8870
+ * `UpdateContinuousBackups` API (PITR does NOT ride on CreateTable).
8871
+ *
8872
+ * CFn shape is `{ PointInTimeRecoveryEnabled: boolean, RecoveryPeriodInDays?: number }`.
8873
+ * Called from both `create()` (after the table is ACTIVE) and `update()`
8874
+ * (only when the value changed). On `update()`-side removal — when the
8875
+ * template drops the block but it was present before — we explicitly
8876
+ * disable PITR (`UpdateContinuousBackups` treats an absent spec as "no
8877
+ * change", so a dropped block must be turned into an explicit
8878
+ * `PointInTimeRecoveryEnabled: false`).
8879
+ */
8880
+ async applyPointInTimeRecovery(tableName, spec, previousSpec) {
8881
+ let enabled;
8882
+ let recoveryPeriodInDays;
8883
+ if (spec !== void 0 && spec !== null) {
8884
+ const s = spec;
8885
+ enabled = Boolean(s["PointInTimeRecoveryEnabled"]);
8886
+ if (enabled && s["RecoveryPeriodInDays"] !== void 0) recoveryPeriodInDays = Number(s["RecoveryPeriodInDays"]);
8887
+ } else if (previousSpec !== void 0 && previousSpec !== null) enabled = false;
8888
+ if (enabled === void 0) return;
8889
+ const pitrSpec = { PointInTimeRecoveryEnabled: enabled };
8890
+ if (recoveryPeriodInDays !== void 0) pitrSpec.RecoveryPeriodInDays = recoveryPeriodInDays;
8891
+ await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new UpdateContinuousBackupsCommand({
8892
+ TableName: tableName,
8893
+ PointInTimeRecoverySpecification: pitrSpec
8894
+ })), `enable PITR on ${tableName}`);
8895
+ this.logger.debug(`Set PointInTimeRecoveryEnabled=${enabled}${recoveryPeriodInDays !== void 0 ? ` RecoveryPeriodInDays=${recoveryPeriodInDays}` : ""} on DynamoDB table ${tableName}`);
8896
+ }
8897
+ /**
8898
+ * Retry a DynamoDB control-plane call on the transient "settling" errors AWS
8899
+ * returns when two table-modifying operations land back-to-back. Enabling
8900
+ * PITR (`UpdateContinuousBackups`) puts the table in a transient state, and a
8901
+ * subsequent `UpdateTimeToLive` is then rejected with "Backups are being
8902
+ * enabled for the table ... Please retry later". `ResourceInUseException`
8903
+ * ("table is being updated") and `LimitExceededException` are the same class.
8904
+ * Backoff: ~2s,4s,8s,16s,30s,30s... bounded to ~2min total, which comfortably
8905
+ * covers the few-second PITR-enable window.
8906
+ */
8907
+ async retryOnTransientControlPlane(op, label, maxAttempts = 8) {
8908
+ let delayMs = 2e3;
8909
+ for (let attempt = 1;; attempt++) try {
8910
+ return await op();
8911
+ } catch (error) {
8912
+ const msg = error instanceof Error ? error.message : String(error);
8913
+ const name = error instanceof Error ? error.name : "";
8914
+ if (!(/being enabled|being updated|please retry later|backups are being/i.test(msg) || name === "ResourceInUseException" || name === "LimitExceededException") || attempt >= maxAttempts) throw error;
8915
+ this.logger.debug(`Transient error on "${label}" (attempt ${attempt}/${maxAttempts}): ${msg} — retrying in ${delayMs}ms`);
8916
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
8917
+ delayMs = Math.min(delayMs * 2, 3e4);
8918
+ }
8919
+ }
8920
+ /**
8921
+ * Apply the table's `TimeToLiveSpecification` via the separate
8922
+ * `UpdateTimeToLive` API (TTL does NOT ride on CreateTable).
8923
+ *
8924
+ * CFn shape is `{ AttributeName: string, Enabled: boolean }`. Called from
8925
+ * both `create()` (after the table is ACTIVE) and `update()` (only when the
8926
+ * value changed). On `update()`-side removal — when the template drops the
8927
+ * block but it was present before — we disable TTL using the PREVIOUS
8928
+ * `AttributeName` (AWS requires the attribute name even to disable TTL).
8929
+ */
8930
+ async applyTimeToLive(tableName, spec, previousSpec) {
8931
+ if (spec !== void 0 && spec !== null) {
8932
+ const s = spec;
8933
+ const attributeName = s["AttributeName"];
8934
+ if (!attributeName) return;
8935
+ const enabled = s["Enabled"] !== void 0 ? Boolean(s["Enabled"]) : true;
8936
+ await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new UpdateTimeToLiveCommand({
8937
+ TableName: tableName,
8938
+ TimeToLiveSpecification: {
8939
+ Enabled: enabled,
8940
+ AttributeName: attributeName
8941
+ }
8942
+ })), `set TTL on ${tableName}`);
8943
+ this.logger.debug(`Set TimeToLive Enabled=${enabled} AttributeName=${attributeName} on DynamoDB table ${tableName}`);
8944
+ return;
8945
+ }
8946
+ if (previousSpec !== void 0 && previousSpec !== null) {
8947
+ const prevAttributeName = previousSpec["AttributeName"];
8948
+ if (!prevAttributeName) return;
8949
+ await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new UpdateTimeToLiveCommand({
8950
+ TableName: tableName,
8951
+ TimeToLiveSpecification: {
8952
+ Enabled: false,
8953
+ AttributeName: prevAttributeName
8954
+ }
8955
+ })), `disable TTL on ${tableName}`);
8956
+ this.logger.debug(`Disabled TimeToLive (AttributeName=${prevAttributeName}) on DynamoDB table ${tableName}`);
8957
+ }
8958
+ }
8959
+ /**
8855
8960
  * Poll DescribeTable until the table reaches ACTIVE status
8856
8961
  *
8857
8962
  * Uses a tight polling loop (1s intervals) instead of CC API's exponential
@@ -8970,6 +9075,26 @@ var DynamoDBTableProvider = class {
8970
9075
  if (err instanceof ResourceNotFoundException$1) return void 0;
8971
9076
  throw err;
8972
9077
  }
9078
+ try {
9079
+ const pitrDesc = (await this.dynamoDBClient.send(new DescribeContinuousBackupsCommand({ TableName: physicalId }))).ContinuousBackupsDescription?.PointInTimeRecoveryDescription;
9080
+ const pitrStatus = pitrDesc?.PointInTimeRecoveryStatus;
9081
+ if (pitrStatus) {
9082
+ const pitr = { PointInTimeRecoveryEnabled: pitrStatus === "ENABLED" };
9083
+ if (pitrStatus === "ENABLED" && pitrDesc?.RecoveryPeriodInDays !== void 0) pitr["RecoveryPeriodInDays"] = pitrDesc.RecoveryPeriodInDays;
9084
+ result["PointInTimeRecoverySpecification"] = pitr;
9085
+ }
9086
+ } catch (err) {
9087
+ this.logger.debug(`Could not read PointInTimeRecovery for ${physicalId}: ${err instanceof Error ? err.message : String(err)}`);
9088
+ }
9089
+ try {
9090
+ const ttlDesc = (await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: physicalId }))).TimeToLiveDescription;
9091
+ if (ttlDesc?.TimeToLiveStatus === "ENABLED" && ttlDesc.AttributeName) result["TimeToLiveSpecification"] = {
9092
+ AttributeName: ttlDesc.AttributeName,
9093
+ Enabled: true
9094
+ };
9095
+ } catch (err) {
9096
+ this.logger.debug(`Could not read TimeToLive for ${physicalId}: ${err instanceof Error ? err.message : String(err)}`);
9097
+ }
8973
9098
  return result;
8974
9099
  } catch (err) {
8975
9100
  if (err instanceof ResourceNotFoundException$1) return void 0;
@@ -51125,7 +51250,7 @@ function reorderArgs(argv) {
51125
51250
  */
51126
51251
  async function main() {
51127
51252
  const program = new Command();
51128
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.171.0");
51253
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.172.0");
51129
51254
  program.addCommand(createBootstrapCommand());
51130
51255
  program.addCommand(createSynthCommand());
51131
51256
  program.addCommand(createListCommand());