@go-to-k/cdkd 0.230.27 → 0.230.28

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,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { A as withErrorHandling, B as generateResourceName, C as StackHasActiveImportsError, F as getLiveRenderer, H as withSkipPrefix, I as PATTERN_B_NAME_OPTIONS, L as PATTERN_B_NAME_PROPERTIES, M as getLogger, P as runStackBuffered, R as PATTERN_B_RESOURCE_TYPES, S as ResourceUpdateNotSupportedError, U as withStackName, V as generateResourceNameWithFallback, _ as MissingCdkCliError, a as assertRegionMatch, b as ProvisioningError, f as LocalInvokeBuildError$1, i as resolveExplicitPhysicalId, k as normalizeAwsError, l as CdkdError, m as LocalStartServiceError, n as matchesCdkPath, o as disableInstanceApiTermination, p as LocalMigrateError, r as normalizeAwsTagsToCfn, s as isTerminationProtectionPropagationError, t as CDK_PATH_TAG, v as NestedStackChildDirectDestroyError, w as StackTerminationProtectionError, x as ResourceTimeoutError, y as PartialFailureError } from "./import-helpers-DayvBD4T.js";
3
3
  import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-pjPwZz1r.js";
4
- import { $ as resolveStateBucketWithDefaultAndSource, A as TemplateParser, B as getDockerCmd, C as findActionableSilentDrops, D as applyRoleArnIfSet, E as cfnRefValueFromPhysicalId, F as AssetPublisher, G as Synthesizer, H as runDockerStreaming, I as stringifyValue, J as getLegacyStateBucketName, K as synthesisStatusMessage, L as WorkGraph, M as S3StateBackend, N as rebuildClientForBucketRegion, O as DiffCalculator, P as shouldRetainResource, Q as resolveStateBucketWithDefault, R as buildDockerImage, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as AssetManifestLoader, V as runDockerForeground, W as getDockerImageBySourceHash, X as resolveCaptureObservedState, Y as resolveApp, Z as resolveSkipPrefix, _ as green, a as withRetry, at as uploadCfnTemplate, b as IAMRoleProvider, c as computeImplicitDeleteEdges, ct as resolveBucketRegion, d as isStatefulRecreateTargetSync, et as warnDeprecatedNoPrefixCliFlag, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as findLargeInlineResources, j as LockManager, k as DagBuilder, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as CFN_TEMPLATE_URL_LIMIT, o as isRetryableTransientError, ot as AssemblyReader, p as formatResourceLine, q as getDefaultStateBucketName, r as DeployEngine, rt as MIGRATE_TMP_PREFIX, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as CFN_TEMPLATE_BODY_LIMIT, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as formatDockerLoginError } from "./deploy-engine-BERaDgMo.js";
4
+ import { $ as resolveStateBucketWithDefaultAndSource, A as TemplateParser, B as getDockerCmd, C as findActionableSilentDrops, D as applyRoleArnIfSet, E as cfnRefValueFromPhysicalId, F as AssetPublisher, G as Synthesizer, H as runDockerStreaming, I as stringifyValue, J as getLegacyStateBucketName, K as synthesisStatusMessage, L as WorkGraph, M as S3StateBackend, N as rebuildClientForBucketRegion, O as DiffCalculator, P as shouldRetainResource, Q as resolveStateBucketWithDefault, R as buildDockerImage, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as AssetManifestLoader, V as runDockerForeground, W as getDockerImageBySourceHash, X as resolveCaptureObservedState, Y as resolveApp, Z as resolveSkipPrefix, _ as green, a as withRetry, at as uploadCfnTemplate, b as IAMRoleProvider, c as computeImplicitDeleteEdges, ct as resolveBucketRegion, d as isStatefulRecreateTargetSync, et as warnDeprecatedNoPrefixCliFlag, f as renderStatefulReason, g as gray, h as cyan, i as withResourceDeadline, it as findLargeInlineResources, j as LockManager, k as DagBuilder, l as extractDeploymentEventError, m as bold, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as CFN_TEMPLATE_URL_LIMIT, o as isRetryableTransientError, ot as AssemblyReader, p as formatResourceLine, q as getDefaultStateBucketName, r as DeployEngine, rt as MIGRATE_TMP_PREFIX, s as IMPLICIT_DELETE_DEPENDENCIES, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as CFN_TEMPLATE_BODY_LIMIT, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, v as red, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, y as yellow, z as formatDockerLoginError } from "./deploy-engine-DhL8rX8u.js";
5
5
  import { t as ASGProvider } from "./asg-provider-Dgj3loIG.js";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  import { createHash, randomBytes, randomUUID } from "node:crypto";
@@ -1445,7 +1445,7 @@ const FLUSH_INTERVAL_MS = 2e3;
1445
1445
  const FLUSH_EVENT_THRESHOLD = 50;
1446
1446
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
1447
1447
  function getCdkdVersion() {
1448
- return "0.230.27";
1448
+ return "0.230.28";
1449
1449
  }
1450
1450
  /**
1451
1451
  * Generate a time-sortable unique run id, e.g.
@@ -55430,7 +55430,7 @@ function reorderArgs(argv) {
55430
55430
  async function main() {
55431
55431
  installPipeCloseHandler();
55432
55432
  const program = new Command();
55433
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.27");
55433
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.230.28");
55434
55434
  program.addCommand(createBootstrapCommand());
55435
55435
  program.addCommand(createSynthCommand());
55436
55436
  program.addCommand(createListCommand());
@@ -7956,6 +7956,28 @@ function stripNullValues(obj) {
7956
7956
  }
7957
7957
  return obj;
7958
7958
  }
7959
+ /**
7960
+ * Thrown when a Cloud Control operation's async progress event reports
7961
+ * FAILED. Carries the handler-reported `ErrorCode` and the operation kind so
7962
+ * the CREATE path can distinguish "our CreateResource materialized a resource
7963
+ * and then failed stabilization" (the remnant must be deleted or every outer
7964
+ * retry collides with AlreadyExists — surfaced by AWS::Synthetics::Canary,
7965
+ * whose create materializes the canary before the IAM-propagation race lands
7966
+ * it in ERROR state) from "the resource already existed before this create"
7967
+ * (`ErrorCode: AlreadyExists` — deleting by that identifier would destroy a
7968
+ * pre-existing user resource, so it is never cleaned up).
7969
+ */
7970
+ var CloudControlOperationFailedError = class CloudControlOperationFailedError extends ProvisioningError {
7971
+ ccErrorCode;
7972
+ ccOperation;
7973
+ constructor(message, resourceType, logicalId, physicalId, ccErrorCode, ccOperation) {
7974
+ super(message, resourceType, logicalId, physicalId);
7975
+ this.ccErrorCode = ccErrorCode;
7976
+ this.ccOperation = ccOperation;
7977
+ this.name = "CloudControlOperationFailedError";
7978
+ Object.setPrototypeOf(this, CloudControlOperationFailedError.prototype);
7979
+ }
7980
+ };
7959
7981
  var CloudControlProvider = class {
7960
7982
  cloudControlClient;
7961
7983
  logger = getLogger().child("CloudControlProvider");
@@ -7990,10 +8012,54 @@ var CloudControlProvider = class {
7990
8012
  result.attributes = await this.enrichResourceAttributes(resourceType, progressEvent.Identifier, result.attributes || {});
7991
8013
  return result;
7992
8014
  } catch (error) {
8015
+ await this.cleanupFailedCreateRemnant(error, resourceType, logicalId);
7993
8016
  this.handleError(error, "CREATE", resourceType, logicalId);
7994
8017
  }
7995
8018
  }
7996
8019
  /**
8020
+ * Best-effort deletion of the physical resource a FAILED async CREATE left
8021
+ * behind.
8022
+ *
8023
+ * Some Cloud Control create handlers materialize the resource first and
8024
+ * stabilize it afterwards (e.g. `AWS::Synthetics::Canary` creates the canary
8025
+ * entity, then builds its backing Lambda). When stabilization fails — most
8026
+ * commonly the just-created-IAM-role propagation race cdkd's fast path is
8027
+ * prone to — the FAILED progress event carries the materialized resource's
8028
+ * `Identifier`, but the half-created remnant keeps occupying the name. The
8029
+ * deploy engine's outer `withRetry` then re-invokes `create()` (the
8030
+ * stabilization message matches the transient-error patterns) and every
8031
+ * retry fails with `AlreadyExists` instead of recovering, and the remnant is
8032
+ * ALSO invisible to rollback (the create never returned, so it is not in
8033
+ * state) — an orphan CloudFormation would have deleted on rollback.
8034
+ *
8035
+ * Deleting the remnant here restores both behaviors: the next retry starts
8036
+ * with a free name (and succeeds once AWS stabilizes), and a final failure
8037
+ * leaves nothing behind.
8038
+ *
8039
+ * Safety: never fires when the handler reported `ErrorCode: AlreadyExists`
8040
+ * — there the identifier names a resource that pre-dates this create (our
8041
+ * CreateCanary repro's SECOND attempt reported exactly that shape), and
8042
+ * deleting it would destroy a user's pre-existing resource. Handlers may
8043
+ * also stuff a speculative identifier into a FAILED event without having
8044
+ * materialized anything (observed on `AWS::CodeDeploy::DeploymentGroup`);
8045
+ * the delete then no-ops via the NotFound-idempotent path. Cleanup failures
8046
+ * are warned, not thrown — the original create error must surface.
8047
+ */
8048
+ async cleanupFailedCreateRemnant(error, resourceType, logicalId) {
8049
+ if (!(error instanceof CloudControlOperationFailedError)) return;
8050
+ if (error.ccOperation !== "CREATE" || !error.physicalId) return;
8051
+ if (error.ccErrorCode === "AlreadyExists") return;
8052
+ if (error.ccErrorCode === "ResourceConflict") return;
8053
+ this.logger.info(`CREATE of ${logicalId} failed after materializing ${error.physicalId}; deleting the remnant so a retry can re-create it`);
8054
+ try {
8055
+ await this.delete(logicalId, error.physicalId, resourceType);
8056
+ this.logger.debug(`Removed failed-create remnant ${error.physicalId} for ${logicalId}`);
8057
+ } catch (cleanupError) {
8058
+ const message = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
8059
+ this.logger.warn(`Failed to delete the remnant ${error.physicalId} left by the failed CREATE of ${logicalId}: ${message} — a retry may fail with AlreadyExists until it is removed manually`);
8060
+ }
8061
+ }
8062
+ /**
7997
8063
  * Update a resource using Cloud Control API
7998
8064
  */
7999
8065
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
@@ -8113,7 +8179,7 @@ var CloudControlProvider = class {
8113
8179
  this.logger.debug(`${operation} ${logicalId}: ${progressEvent.OperationStatus} (attempt ${attempts}, next poll ${pollInterval}ms)`);
8114
8180
  switch (progressEvent.OperationStatus) {
8115
8181
  case "SUCCESS": return progressEvent;
8116
- case "FAILED": throw new ProvisioningError(`${operation} failed for ${logicalId}: ${progressEvent.StatusMessage || "Unknown error"}`, progressEvent.TypeName || "Unknown", logicalId, progressEvent.Identifier);
8182
+ case "FAILED": throw new CloudControlOperationFailedError(`${operation} failed for ${logicalId}: ${progressEvent.StatusMessage || "Unknown error"}`, progressEvent.TypeName || "Unknown", logicalId, progressEvent.Identifier, progressEvent.ErrorCode, operation);
8117
8183
  case "CANCEL_COMPLETE": throw new ProvisioningError(`${operation} cancelled for ${logicalId}`, progressEvent.TypeName || "Unknown", logicalId, progressEvent.Identifier);
8118
8184
  case "IN_PROGRESS":
8119
8185
  case "PENDING":
@@ -14221,4 +14287,4 @@ var DeployEngine = class {
14221
14287
 
14222
14288
  //#endregion
14223
14289
  export { resolveStateBucketWithDefaultAndSource as $, TemplateParser as A, getDockerCmd as B, findActionableSilentDrops as C, applyRoleArnIfSet as D, cfnRefValueFromPhysicalId as E, AssetPublisher as F, Synthesizer as G, runDockerStreaming as H, stringifyValue as I, getLegacyStateBucketName as J, synthesisStatusMessage as K, WorkGraph as L, S3StateBackend as M, rebuildClientForBucketRegion as N, DiffCalculator as O, shouldRetainResource as P, resolveStateBucketWithDefault as Q, buildDockerImage as R, ProviderRegistry as S, IntrinsicFunctionResolver as T, AssetManifestLoader as U, runDockerForeground as V, getDockerImageBySourceHash as W, resolveCaptureObservedState as X, resolveApp as Y, resolveSkipPrefix as Z, green as _, withRetry as a, uploadCfnTemplate as at, IAMRoleProvider as b, computeImplicitDeleteEdges as c, resolveBucketRegion as ct, isStatefulRecreateTargetSync as d, warnDeprecatedNoPrefixCliFlag as et, renderStatefulReason as f, gray as g, cyan as h, withResourceDeadline as i, findLargeInlineResources as it, LockManager as j, DagBuilder as k, extractDeploymentEventError as l, bold as m, DEFAULT_RESOURCE_WARN_AFTER_MS as n, CFN_TEMPLATE_URL_LIMIT as nt, isRetryableTransientError as o, AssemblyReader as ot, formatResourceLine as p, getDefaultStateBucketName as q, DeployEngine as r, MIGRATE_TMP_PREFIX as rt, IMPLICIT_DELETE_DEPENDENCIES as s, clearBucketRegionCache as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, CFN_TEMPLATE_BODY_LIMIT as tt, MULTI_REGION_RECREATE_BLOCKED_TYPES as u, red as v, CloudControlProvider as w, collectInlinePolicyNamesManagedBySiblings as x, yellow as y, formatDockerLoginError as z };
14224
- //# sourceMappingURL=deploy-engine-BERaDgMo.js.map
14290
+ //# sourceMappingURL=deploy-engine-DhL8rX8u.js.map