@go-to-k/cdkd 0.159.3 → 0.161.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 +102 -17
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-BzrECC3i.js → deploy-engine-BC1Z7ABm.js} +331 -167
- package/dist/deploy-engine-BC1Z7ABm.js.map +1 -0
- package/dist/index.d.ts +35 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-BzrECC3i.js.map +0 -1
|
@@ -3354,7 +3354,8 @@ const STATE_SCHEMA_VERSIONS_READABLE = [
|
|
|
3354
3354
|
3,
|
|
3355
3355
|
4,
|
|
3356
3356
|
5,
|
|
3357
|
-
6
|
|
3357
|
+
6,
|
|
3358
|
+
7
|
|
3358
3359
|
];
|
|
3359
3360
|
/**
|
|
3360
3361
|
* Returns true when a recorded `DeletionPolicy` should prevent cdkd from
|
|
@@ -3597,7 +3598,7 @@ var S3StateBackend = class {
|
|
|
3597
3598
|
const { expectedEtag, migrateLegacy } = options;
|
|
3598
3599
|
const body = {
|
|
3599
3600
|
...state,
|
|
3600
|
-
version:
|
|
3601
|
+
version: 7,
|
|
3601
3602
|
stackName,
|
|
3602
3603
|
region
|
|
3603
3604
|
};
|
|
@@ -9864,20 +9865,25 @@ const PROPERTY_COVERAGE_BY_TYPE = new Map([
|
|
|
9864
9865
|
//#endregion
|
|
9865
9866
|
//#region src/provisioning/property-coverage.ts
|
|
9866
9867
|
/**
|
|
9867
|
-
* Helpers for cdkd's deploy-time property-coverage
|
|
9868
|
+
* Helpers for cdkd's deploy-time property-coverage check.
|
|
9868
9869
|
*
|
|
9869
9870
|
* The data ({@link PROPERTY_COVERAGE_BY_TYPE}) is generated by
|
|
9870
9871
|
* `scripts/gen-property-coverage.ts` (run via `vp run gen:property-coverage`)
|
|
9871
9872
|
* from the CFn schema fixtures (`tests/fixtures/cfn-schemas/*.json`) and
|
|
9872
9873
|
* each SDK provider's `handledProperties` / `unhandledByDesign` declarations.
|
|
9873
9874
|
* This module adds the runtime predicates + the actionable issue link used
|
|
9874
|
-
* by the
|
|
9875
|
+
* by the routing decision (see
|
|
9876
|
+
* {@link ./provider-registry.ProviderRegistry.getProviderFor} and
|
|
9877
|
+
* {@link ./provider-registry.ProviderRegistry.reportSilentDropDecisions}).
|
|
9875
9878
|
*
|
|
9876
|
-
*
|
|
9877
|
-
*
|
|
9878
|
-
*
|
|
9879
|
-
*
|
|
9880
|
-
*
|
|
9879
|
+
* Behavior: when a template uses a top-level CFn property cdkd's SDK
|
|
9880
|
+
* Provider does not write to AWS (= silent drop), the resource is
|
|
9881
|
+
* **auto-routed via Cloud Control API** by default — CC forwards the
|
|
9882
|
+
* full property map verbatim, closing the silent-drop bug (#614). The
|
|
9883
|
+
* user can opt out per-property via
|
|
9884
|
+
* `--allow-unsupported-properties <Type:Prop>,...`, which keeps the
|
|
9885
|
+
* resource on the SDK Provider path and accepts the silent drop (a
|
|
9886
|
+
* warn line is logged for auditability).
|
|
9881
9887
|
*/
|
|
9882
9888
|
/**
|
|
9883
9889
|
* Look up a Tier 1 type's property-coverage record. Returns `undefined` for
|
|
@@ -9914,24 +9920,48 @@ function findSilentDropProperties(resourceType, templateProperties) {
|
|
|
9914
9920
|
return drops.sort((a, b) => a.property.localeCompare(b.property));
|
|
9915
9921
|
}
|
|
9916
9922
|
/**
|
|
9917
|
-
*
|
|
9918
|
-
*
|
|
9919
|
-
*
|
|
9920
|
-
*
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9923
|
+
* Same as {@link findSilentDropProperties} but filters out entries whose
|
|
9924
|
+
* `<Type>:<Prop>` key is in the supplied allow set (the
|
|
9925
|
+
* `--allow-unsupported-properties` user override). Returned drops are the
|
|
9926
|
+
* ones that should drive CC API auto-routing (issue
|
|
9927
|
+
* [#614](https://github.com/go-to-k/cdkd/issues/614)) — silent drops
|
|
9928
|
+
* the user has explicitly opted-into via the override are removed so the
|
|
9929
|
+
* resource stays on the SDK Provider path.
|
|
9930
|
+
*
|
|
9931
|
+
* Mirrors `findSilentDropProperties`'s sort + early-return behavior:
|
|
9932
|
+
* returns `[]` for Tier 2 / Custom / unknown types, undefined / empty
|
|
9933
|
+
* `templateProperties`, or when every drop is in `allowedKeys`.
|
|
9934
|
+
*/
|
|
9935
|
+
function findActionableSilentDrops(resourceType, templateProperties, allowedKeys) {
|
|
9936
|
+
const drops = findSilentDropProperties(resourceType, templateProperties);
|
|
9937
|
+
if (drops.length === 0) return drops;
|
|
9938
|
+
return drops.filter(({ property }) => !allowedKeys.has(`${resourceType}:${property}`));
|
|
9924
9939
|
}
|
|
9925
9940
|
|
|
9926
9941
|
//#endregion
|
|
9927
9942
|
//#region src/provisioning/provider-registry.ts
|
|
9928
9943
|
/**
|
|
9929
|
-
* Provider registry for managing resource providers
|
|
9930
|
-
*
|
|
9931
|
-
*
|
|
9932
|
-
* 1.
|
|
9933
|
-
*
|
|
9934
|
-
*
|
|
9944
|
+
* Provider registry for managing resource providers.
|
|
9945
|
+
*
|
|
9946
|
+
* Selection strategy for a fresh resource (see {@link getProviderFor}):
|
|
9947
|
+
* 1. Custom Resource (`Custom::*` / `AWS::CloudFormation::CustomResource`)
|
|
9948
|
+
* → Custom Resource provider (recorded as `provisionedBy: 'sdk'`).
|
|
9949
|
+
* 2. Existing-state `provisionedBy: 'cc-api'` → Cloud Control (sticky).
|
|
9950
|
+
* 3. SDK Provider registered, no silent-drop properties (after the
|
|
9951
|
+
* `--allow-unsupported-properties` override filter) → SDK Provider.
|
|
9952
|
+
* 4. SDK Provider registered, silent-drop properties present, NOT all
|
|
9953
|
+
* in the allow set → Cloud Control (auto-route, info-logged).
|
|
9954
|
+
* 5. SDK Provider registered, silent-drop properties present, ALL in
|
|
9955
|
+
* the allow set → SDK Provider (the user explicitly accepted the
|
|
9956
|
+
* silent drop, warn-logged).
|
|
9957
|
+
* 6. No SDK Provider, Cloud Control supports the type → Cloud Control.
|
|
9958
|
+
* 7. `--allow-unsupported-types` escape hatch → Cloud Control optimistically.
|
|
9959
|
+
* 8. Otherwise → throw (no provider available).
|
|
9960
|
+
*
|
|
9961
|
+
* Tier 3 (`NON_PROVISIONABLE`) types are rejected earlier by
|
|
9962
|
+
* {@link validateResourceTypes}; the silent-drop auto-route only fires for
|
|
9963
|
+
* Tier 1 types whose SDK Provider declares `handledProperties` and where
|
|
9964
|
+
* Cloud Control is guaranteed to be a viable alternative.
|
|
9935
9965
|
*/
|
|
9936
9966
|
var ProviderRegistry = class {
|
|
9937
9967
|
logger = getLogger().child("ProviderRegistry");
|
|
@@ -9961,10 +9991,12 @@ var ProviderRegistry = class {
|
|
|
9961
9991
|
/**
|
|
9962
9992
|
* Escape hatch for the `--allow-unsupported-properties` CLI flag. Each entry
|
|
9963
9993
|
* is a `<ResourceType>:<PropertyName>` token (e.g.
|
|
9964
|
-
* `AWS::Lambda::Function:LoggingConfig`).
|
|
9965
|
-
*
|
|
9966
|
-
*
|
|
9967
|
-
*
|
|
9994
|
+
* `AWS::Lambda::Function:LoggingConfig`). As of issue
|
|
9995
|
+
* [#614](https://github.com/go-to-k/cdkd/issues/614), the flag now means
|
|
9996
|
+
* "force the SDK Provider path and accept the silent drop" — the default
|
|
9997
|
+
* for an un-flagged silent-drop property is to auto-route the resource
|
|
9998
|
+
* through Cloud Control instead. Per-type-property (not blanket) so the
|
|
9999
|
+
* user explicitly acknowledges each silent drop they accept.
|
|
9968
10000
|
*/
|
|
9969
10001
|
allowUnsupportedProperties(entries) {
|
|
9970
10002
|
for (const entry of entries) {
|
|
@@ -10007,38 +10039,84 @@ var ProviderRegistry = class {
|
|
|
10007
10039
|
this.providers.delete(resourceType);
|
|
10008
10040
|
}
|
|
10009
10041
|
/**
|
|
10010
|
-
*
|
|
10042
|
+
* Resolve the provider for a resource using the full routing decision
|
|
10043
|
+
* matrix (see class docstring). The returned object carries the chosen
|
|
10044
|
+
* provider, the `provisionedBy` layer label to persist on the resource's
|
|
10045
|
+
* state record, and (for the CC auto-route case) the names of the
|
|
10046
|
+
* silent-drop properties that drove the decision so callers can render
|
|
10047
|
+
* `[via CC API: <reason>]` plan annotations.
|
|
10011
10048
|
*
|
|
10012
|
-
*
|
|
10013
|
-
* 1. If specific SDK provider is registered, use it
|
|
10014
|
-
* 2. Otherwise, use Cloud Control API if supported
|
|
10015
|
-
* 3. Throw error if no provider available
|
|
10016
|
-
*
|
|
10017
|
-
* @param resourceType CloudFormation resource type
|
|
10018
|
-
* @returns Provider instance
|
|
10019
|
-
* @throws Error if no provider available
|
|
10049
|
+
* @throws Error if no provider can be found for the type.
|
|
10020
10050
|
*/
|
|
10021
|
-
|
|
10051
|
+
getProviderFor(input) {
|
|
10052
|
+
const { resourceType, properties, provisionedBy } = input;
|
|
10053
|
+
if (isCustomResource(resourceType)) {
|
|
10054
|
+
this.logger.debug(`Using Custom Resource provider for ${resourceType}`);
|
|
10055
|
+
return {
|
|
10056
|
+
provider: this.customResourceProvider,
|
|
10057
|
+
provisionedBy: "sdk"
|
|
10058
|
+
};
|
|
10059
|
+
}
|
|
10060
|
+
if (provisionedBy === "cc-api") {
|
|
10061
|
+
this.logger.debug(`Routing ${resourceType} via Cloud Control (state-recorded provisionedBy=cc-api)`);
|
|
10062
|
+
return {
|
|
10063
|
+
provider: this.cloudControlProvider,
|
|
10064
|
+
provisionedBy: "cc-api"
|
|
10065
|
+
};
|
|
10066
|
+
}
|
|
10022
10067
|
const specificProvider = this.providers.get(resourceType);
|
|
10023
10068
|
if (specificProvider) {
|
|
10024
|
-
|
|
10025
|
-
|
|
10069
|
+
const actionableDrops = findActionableSilentDrops(resourceType, properties, this.allowedUnsupportedProperties);
|
|
10070
|
+
if (actionableDrops.length === 0) {
|
|
10071
|
+
this.logger.debug(`Using specific SDK provider for ${resourceType}`);
|
|
10072
|
+
return {
|
|
10073
|
+
provider: specificProvider,
|
|
10074
|
+
provisionedBy: "sdk"
|
|
10075
|
+
};
|
|
10076
|
+
}
|
|
10077
|
+
this.logger.debug(`Auto-routing ${resourceType} via Cloud Control (silent-drop properties: ${actionableDrops.map((d) => d.property).join(", ")})`);
|
|
10078
|
+
return {
|
|
10079
|
+
provider: this.cloudControlProvider,
|
|
10080
|
+
provisionedBy: "cc-api",
|
|
10081
|
+
ccRouteReason: { properties: actionableDrops.map((d) => d.property) }
|
|
10082
|
+
};
|
|
10026
10083
|
}
|
|
10027
10084
|
if (CloudControlProvider.isSupportedResourceType(resourceType)) {
|
|
10028
10085
|
this.logger.debug(`Using Cloud Control API provider for ${resourceType}`);
|
|
10029
|
-
return
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
return this.customResourceProvider;
|
|
10086
|
+
return {
|
|
10087
|
+
provider: this.cloudControlProvider,
|
|
10088
|
+
provisionedBy: "cc-api"
|
|
10089
|
+
};
|
|
10034
10090
|
}
|
|
10035
10091
|
if (this.allowedUnsupportedTypes.has(resourceType)) {
|
|
10036
10092
|
this.logger.debug(`Routing escape-hatch-allowed type ${resourceType} through Cloud Control API`);
|
|
10037
|
-
return
|
|
10093
|
+
return {
|
|
10094
|
+
provider: this.cloudControlProvider,
|
|
10095
|
+
provisionedBy: "cc-api"
|
|
10096
|
+
};
|
|
10038
10097
|
}
|
|
10039
10098
|
throw new Error(`No provider available for resource type: ${resourceType}. This resource type is not supported by Cloud Control API and no SDK provider is registered.`);
|
|
10040
10099
|
}
|
|
10041
10100
|
/**
|
|
10101
|
+
* Legacy entry point that returns just the provider. Delegates to
|
|
10102
|
+
* {@link getProviderFor} with no properties / no state-recorded layer —
|
|
10103
|
+
* which means silent-drop auto-routing CANNOT fire (no template to
|
|
10104
|
+
* inspect) and `provisionedBy === undefined` is treated as SDK semantics
|
|
10105
|
+
* (legacy default). Use {@link getProviderFor} when the caller has
|
|
10106
|
+
* properties / state — otherwise a CC-managed existing resource will get
|
|
10107
|
+
* an SDK Provider on its update / delete path, which is the
|
|
10108
|
+
* silent-data-corruption hazard that v7's schema bump is meant to
|
|
10109
|
+
* prevent.
|
|
10110
|
+
*
|
|
10111
|
+
* Kept on the public surface for the destroy / drift / state-refresh
|
|
10112
|
+
* paths whose call sites only know the resource type (the caller should
|
|
10113
|
+
* still thread `provisionedBy` from state when it's available; this
|
|
10114
|
+
* shape is only safe for type-only callers).
|
|
10115
|
+
*/
|
|
10116
|
+
getProvider(resourceType) {
|
|
10117
|
+
return this.getProviderFor({ resourceType }).provider;
|
|
10118
|
+
}
|
|
10119
|
+
/**
|
|
10042
10120
|
* Check if a resource type should be skipped
|
|
10043
10121
|
*/
|
|
10044
10122
|
shouldSkipResource(resourceType) {
|
|
@@ -10050,7 +10128,7 @@ var ProviderRegistry = class {
|
|
|
10050
10128
|
hasProvider(resourceType) {
|
|
10051
10129
|
if (this.shouldSkipResource(resourceType)) return true;
|
|
10052
10130
|
if (this.allowedUnsupportedTypes.has(resourceType)) return true;
|
|
10053
|
-
return this.providers.has(resourceType) || CloudControlProvider.isSupportedResourceType(resourceType) || resourceType
|
|
10131
|
+
return this.providers.has(resourceType) || CloudControlProvider.isSupportedResourceType(resourceType) || isCustomResource(resourceType);
|
|
10054
10132
|
}
|
|
10055
10133
|
/**
|
|
10056
10134
|
* Get the Cloud Control provider instance (for resource state lookup)
|
|
@@ -10095,77 +10173,96 @@ var ProviderRegistry = class {
|
|
|
10095
10173
|
this.logger.debug(`Validated ${resourceTypes.size} resource types: all have available providers`);
|
|
10096
10174
|
}
|
|
10097
10175
|
/**
|
|
10098
|
-
*
|
|
10099
|
-
*
|
|
10100
|
-
*
|
|
10101
|
-
*
|
|
10102
|
-
* Control
|
|
10103
|
-
*
|
|
10176
|
+
* Walk every resource in the template and identify top-level CFn
|
|
10177
|
+
* properties cdkd's SDK provider would silently drop on write. As of
|
|
10178
|
+
* issue [#614](https://github.com/go-to-k/cdkd/issues/614), this method
|
|
10179
|
+
* **no longer throws** — silent drops now auto-route the resource through
|
|
10180
|
+
* Cloud Control API by default (see {@link getProviderFor}). The method
|
|
10181
|
+
* is retained on the name `validateResourceProperties` so existing deploy
|
|
10182
|
+
* call sites continue to work; it now emits info-level routing decisions
|
|
10183
|
+
* for each silent-drop resource, plus warn-level lines for resources
|
|
10184
|
+
* where the user explicitly opted into the silent drop via
|
|
10185
|
+
* `--allow-unsupported-properties`.
|
|
10104
10186
|
*
|
|
10105
10187
|
* Must be called AFTER {@link validateResourceTypes} — type-level errors
|
|
10106
|
-
* are
|
|
10107
|
-
* the
|
|
10108
|
-
*
|
|
10188
|
+
* are still hard rejects. For a type allowed via `--allow-unsupported-types`,
|
|
10189
|
+
* the property check is a no-op (`findSilentDropProperties` returns `[]`
|
|
10190
|
+
* for non-Tier-1 / unknown types).
|
|
10191
|
+
*
|
|
10192
|
+
* @see findAutoRouteHits for the pure-functional pre-deploy plan-builder
|
|
10193
|
+
* that returns the same information without logging.
|
|
10109
10194
|
*/
|
|
10110
10195
|
validateResourceProperties(resources) {
|
|
10111
|
-
|
|
10112
|
-
|
|
10196
|
+
this.reportSilentDropDecisions(resources);
|
|
10197
|
+
}
|
|
10198
|
+
/**
|
|
10199
|
+
* Info-log every silent-drop routing decision (auto-route via CC API) and
|
|
10200
|
+
* warn-log every silent drop the user explicitly opted into via
|
|
10201
|
+
* `--allow-unsupported-properties` (forced SDK path, the property will
|
|
10202
|
+
* be dropped). Pure side-effect — does not mutate state and never throws.
|
|
10203
|
+
*
|
|
10204
|
+
* Issue [#614](https://github.com/go-to-k/cdkd/issues/614). Replaces the
|
|
10205
|
+
* pre-v0.16x throw path: silent drops are now a routing signal, not an
|
|
10206
|
+
* error.
|
|
10207
|
+
*
|
|
10208
|
+
* When the optional `provisionedBy` (from existing state) is `'cc-api'`,
|
|
10209
|
+
* the auto-route info line is demoted to `debug` — the resource has been
|
|
10210
|
+
* on CC for at least one prior deploy, so the routing decision is
|
|
10211
|
+
* **continuation of sticky state, not a fresh auto-route**. Surfacing the
|
|
10212
|
+
* info line every deploy would be repetitive noise. The warn line for
|
|
10213
|
+
* explicit `--allow-unsupported-properties` overrides is NOT demoted —
|
|
10214
|
+
* that override is an active user choice for THIS deploy and should
|
|
10215
|
+
* surface every time.
|
|
10216
|
+
*/
|
|
10217
|
+
reportSilentDropDecisions(resources) {
|
|
10218
|
+
for (const { logicalId, resourceType, properties, provisionedBy } of resources) {
|
|
10113
10219
|
const drops = findSilentDropProperties(resourceType, properties);
|
|
10114
|
-
|
|
10220
|
+
if (drops.length === 0) continue;
|
|
10221
|
+
const overridden = [];
|
|
10222
|
+
const autoRouted = [];
|
|
10223
|
+
for (const { property } of drops) {
|
|
10115
10224
|
const allowKey = `${resourceType}:${property}`;
|
|
10116
|
-
if (this.allowedUnsupportedProperties.has(allowKey))
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10225
|
+
if (this.allowedUnsupportedProperties.has(allowKey)) overridden.push(property);
|
|
10226
|
+
else autoRouted.push(property);
|
|
10227
|
+
}
|
|
10228
|
+
if (autoRouted.length > 0) {
|
|
10229
|
+
const message = `${logicalId} (${resourceType}): routing via Cloud Control API (cdkd's SDK Provider does not yet wire ${autoRouted.join(", ")} — CC API will forward the full property map. Override via --allow-unsupported-properties ${autoRouted.map((p) => `${resourceType}:${p}`).join(",")}.)`;
|
|
10230
|
+
if (provisionedBy === "cc-api") this.logger.debug(message);
|
|
10231
|
+
else this.logger.info(message);
|
|
10232
|
+
}
|
|
10233
|
+
if (overridden.length > 0) {
|
|
10234
|
+
const propList = overridden.join(", ");
|
|
10235
|
+
this.logger.warn(`${logicalId} (${resourceType}): ${propList} will be silently dropped (--allow-unsupported-properties override accepted). Remove the override to route this resource via Cloud Control API instead.`);
|
|
10123
10236
|
}
|
|
10124
10237
|
}
|
|
10125
|
-
if (errors.length === 0) return;
|
|
10126
|
-
throw new Error(renderPropertyCoverageError(errors));
|
|
10127
10238
|
}
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
*
|
|
10131
|
-
*
|
|
10132
|
-
*
|
|
10133
|
-
*
|
|
10134
|
-
*
|
|
10135
|
-
*
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10239
|
+
/**
|
|
10240
|
+
* Pure-functional discovery of every resource whose template uses one or
|
|
10241
|
+
* more silent-drop properties that are NOT in the
|
|
10242
|
+
* `--allow-unsupported-properties` allow set — i.e. every resource that
|
|
10243
|
+
* {@link getProviderFor} would auto-route via Cloud Control. Returned
|
|
10244
|
+
* entries carry the silent-drop property names so plan / diff renderers
|
|
10245
|
+
* can show `[via CC API: LoggingConfig]`.
|
|
10246
|
+
*
|
|
10247
|
+
* Does NOT log or throw. Use {@link reportSilentDropDecisions} for the
|
|
10248
|
+
* side-effecting info / warn surface.
|
|
10249
|
+
*/
|
|
10250
|
+
findAutoRouteHits(resources) {
|
|
10251
|
+
const hits = [];
|
|
10252
|
+
for (const { logicalId, resourceType, properties } of resources) {
|
|
10253
|
+
const actionable = findActionableSilentDrops(resourceType, properties, this.allowedUnsupportedProperties);
|
|
10254
|
+
if (actionable.length === 0) continue;
|
|
10255
|
+
hits.push({
|
|
10256
|
+
logicalId,
|
|
10257
|
+
resourceType,
|
|
10258
|
+
properties: actionable.map((d) => d.property)
|
|
10259
|
+
});
|
|
10147
10260
|
}
|
|
10148
|
-
|
|
10149
|
-
property: e.property,
|
|
10150
|
-
rationale: e.rationale
|
|
10151
|
-
});
|
|
10261
|
+
return hits;
|
|
10152
10262
|
}
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
const { resourceType, props } = byLogicalId.get(logicalId);
|
|
10157
|
-
const propLines = [...props].sort((a, b) => a.property.localeCompare(b.property)).map(({ property, rationale }) => {
|
|
10158
|
-
return ` - ${property}\n ${rationale}\n Request support: ${unsupportedPropertyIssueUrl(resourceType, property)}`;
|
|
10159
|
-
}).join("\n");
|
|
10160
|
-
sections.push(` ${logicalId} (${resourceType}):\n${propLines}`);
|
|
10161
|
-
}
|
|
10162
|
-
const dedupRerun = Array.from(new Set(errors.map((e) => `${e.resourceType}:${e.property}`))).join(",");
|
|
10163
|
-
return `cdkd would silently drop these properties at deploy time:\n\n` + sections.join("\n\n") + `
|
|
10164
|
-
|
|
10165
|
-
These properties exist in your CDK code but cdkd will not write them to AWS. The deployed resource will be missing these fields.
|
|
10166
|
-
|
|
10167
|
-
To proceed anyway (accepts the silent drop), re-run with:
|
|
10168
|
-
--allow-unsupported-properties ${dedupRerun}`;
|
|
10263
|
+
};
|
|
10264
|
+
function isCustomResource(resourceType) {
|
|
10265
|
+
return resourceType.startsWith("Custom::") || resourceType === "AWS::CloudFormation::CustomResource";
|
|
10169
10266
|
}
|
|
10170
10267
|
|
|
10171
10268
|
//#endregion
|
|
@@ -11283,6 +11380,36 @@ var InterruptedError = class extends Error {
|
|
|
11283
11380
|
this.name = "InterruptedError";
|
|
11284
11381
|
}
|
|
11285
11382
|
};
|
|
11383
|
+
/**
|
|
11384
|
+
* Best-effort routing inference for the live-progress task label
|
|
11385
|
+
* (#614 §9). Mirrors the routing decision tree but is purely cosmetic:
|
|
11386
|
+
* errors here never surface — when the inference fails we return
|
|
11387
|
+
* `undefined` and the label gets no `[CC API]` tag. The real
|
|
11388
|
+
* `getProviderFor` call inside the deploy/destroy critical path is the
|
|
11389
|
+
* load-bearing dispatch.
|
|
11390
|
+
*
|
|
11391
|
+
* Inputs:
|
|
11392
|
+
* - CREATE / UPDATE → template-side `desiredProperties` (top-level CFn
|
|
11393
|
+
* property names; intrinsic resolution does not change those, so we
|
|
11394
|
+
* can route ahead of the resolver run).
|
|
11395
|
+
* - DELETE → sticky `provisionedBy` from the existing-state record.
|
|
11396
|
+
*
|
|
11397
|
+
* Exported so {@link DeployEngine.peekRoutingForLabel} stays a 1-line
|
|
11398
|
+
* delegate and the routing-inference logic is directly unit-testable
|
|
11399
|
+
* without standing up a full DeployEngine harness.
|
|
11400
|
+
*/
|
|
11401
|
+
function deriveLabelRouting(change, existingState, registry) {
|
|
11402
|
+
try {
|
|
11403
|
+
if (change.changeType === "DELETE") return existingState?.provisionedBy;
|
|
11404
|
+
return registry.getProviderFor({
|
|
11405
|
+
resourceType: change.resourceType,
|
|
11406
|
+
properties: change.desiredProperties,
|
|
11407
|
+
provisionedBy: existingState?.provisionedBy
|
|
11408
|
+
}).provisionedBy;
|
|
11409
|
+
} catch {
|
|
11410
|
+
return;
|
|
11411
|
+
}
|
|
11412
|
+
}
|
|
11286
11413
|
var DeployEngine = class {
|
|
11287
11414
|
logger = getLogger().child("DeployEngine");
|
|
11288
11415
|
resolver;
|
|
@@ -11505,7 +11632,7 @@ var DeployEngine = class {
|
|
|
11505
11632
|
try {
|
|
11506
11633
|
const currentStateData = await this.stateBackend.getState(stackName, this.stackRegion);
|
|
11507
11634
|
const currentState = currentStateData?.state ?? {
|
|
11508
|
-
version:
|
|
11635
|
+
version: 7,
|
|
11509
11636
|
region: this.stackRegion,
|
|
11510
11637
|
stackName,
|
|
11511
11638
|
resources: {},
|
|
@@ -11532,7 +11659,8 @@ var DeployEngine = class {
|
|
|
11532
11659
|
const resourcesForPropertyCheck = Object.entries(template.Resources || {}).filter(([, r]) => r.Type !== "AWS::CDK::Metadata").map(([logicalId, r]) => ({
|
|
11533
11660
|
logicalId,
|
|
11534
11661
|
resourceType: r.Type,
|
|
11535
|
-
properties: r.Properties
|
|
11662
|
+
properties: r.Properties,
|
|
11663
|
+
provisionedBy: currentState.resources[logicalId]?.provisionedBy
|
|
11536
11664
|
}));
|
|
11537
11665
|
this.providerRegistry.validateResourceProperties(resourcesForPropertyCheck);
|
|
11538
11666
|
this.logger.debug(`All resource properties validated`);
|
|
@@ -11553,7 +11681,7 @@ var DeployEngine = class {
|
|
|
11553
11681
|
await this.drainObservedCaptures(currentState.resources);
|
|
11554
11682
|
try {
|
|
11555
11683
|
const refreshedState = {
|
|
11556
|
-
version:
|
|
11684
|
+
version: 7,
|
|
11557
11685
|
region: this.stackRegion,
|
|
11558
11686
|
stackName: currentState.stackName,
|
|
11559
11687
|
resources: currentState.resources,
|
|
@@ -11653,7 +11781,7 @@ var DeployEngine = class {
|
|
|
11653
11781
|
saveChain = saveChain.then(async () => {
|
|
11654
11782
|
try {
|
|
11655
11783
|
const partialState = {
|
|
11656
|
-
version:
|
|
11784
|
+
version: 7,
|
|
11657
11785
|
region: this.stackRegion,
|
|
11658
11786
|
stackName: currentState.stackName,
|
|
11659
11787
|
resources: newResources,
|
|
@@ -11711,6 +11839,7 @@ var DeployEngine = class {
|
|
|
11711
11839
|
logicalId,
|
|
11712
11840
|
changeType: change.changeType,
|
|
11713
11841
|
resourceType: change.resourceType,
|
|
11842
|
+
provisionedBy: newResources[logicalId]?.provisionedBy ?? previousState?.provisionedBy,
|
|
11714
11843
|
previousState,
|
|
11715
11844
|
physicalId: newResources[logicalId]?.physicalId,
|
|
11716
11845
|
properties: newResources[logicalId]?.properties
|
|
@@ -11747,6 +11876,7 @@ var DeployEngine = class {
|
|
|
11747
11876
|
logicalId,
|
|
11748
11877
|
changeType: "DELETE",
|
|
11749
11878
|
resourceType: change.resourceType,
|
|
11879
|
+
provisionedBy: previousState?.provisionedBy,
|
|
11750
11880
|
previousState
|
|
11751
11881
|
});
|
|
11752
11882
|
saveStateAfterResource(logicalId);
|
|
@@ -11759,7 +11889,7 @@ var DeployEngine = class {
|
|
|
11759
11889
|
} catch (error) {
|
|
11760
11890
|
try {
|
|
11761
11891
|
const preRollbackState = {
|
|
11762
|
-
version:
|
|
11892
|
+
version: 7,
|
|
11763
11893
|
region: this.stackRegion,
|
|
11764
11894
|
stackName: currentState.stackName,
|
|
11765
11895
|
resources: newResources,
|
|
@@ -11788,7 +11918,7 @@ var DeployEngine = class {
|
|
|
11788
11918
|
} else await this.performRollback(completedOperations, newResources, stackName);
|
|
11789
11919
|
try {
|
|
11790
11920
|
const postRollbackState = {
|
|
11791
|
-
version:
|
|
11921
|
+
version: 7,
|
|
11792
11922
|
region: this.stackRegion,
|
|
11793
11923
|
stackName: currentState.stackName,
|
|
11794
11924
|
resources: newResources,
|
|
@@ -11803,7 +11933,7 @@ var DeployEngine = class {
|
|
|
11803
11933
|
try {
|
|
11804
11934
|
const freshEtag = (await this.stateBackend.getState(stackName, this.stackRegion))?.etag;
|
|
11805
11935
|
const postRollbackState = {
|
|
11806
|
-
version:
|
|
11936
|
+
version: 7,
|
|
11807
11937
|
region: this.stackRegion,
|
|
11808
11938
|
stackName: currentState.stackName,
|
|
11809
11939
|
resources: newResources,
|
|
@@ -11822,7 +11952,7 @@ var DeployEngine = class {
|
|
|
11822
11952
|
const outputs = await this.resolveOutputs(template, newResources, stackName, parameterValues, conditions);
|
|
11823
11953
|
return {
|
|
11824
11954
|
state: {
|
|
11825
|
-
version:
|
|
11955
|
+
version: 7,
|
|
11826
11956
|
region: this.stackRegion,
|
|
11827
11957
|
stackName: currentState.stackName,
|
|
11828
11958
|
resources: newResources,
|
|
@@ -11922,23 +12052,31 @@ var DeployEngine = class {
|
|
|
11922
12052
|
async performSingleRollback(op, stateResources) {
|
|
11923
12053
|
try {
|
|
11924
12054
|
switch (op.changeType) {
|
|
11925
|
-
case "CREATE":
|
|
12055
|
+
case "CREATE": {
|
|
11926
12056
|
if (!op.physicalId) {
|
|
11927
12057
|
this.logger.warn(` Rollback: Cannot delete ${op.logicalId} — no physical ID recorded`);
|
|
11928
12058
|
break;
|
|
11929
12059
|
}
|
|
11930
12060
|
this.logger.info(` Rollback: Deleting created resource ${op.logicalId} (${op.resourceType})`);
|
|
11931
|
-
|
|
12061
|
+
const { provider } = this.providerRegistry.getProviderFor({
|
|
12062
|
+
resourceType: op.resourceType,
|
|
12063
|
+
provisionedBy: op.provisionedBy
|
|
12064
|
+
});
|
|
12065
|
+
await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.properties, { expectedRegion: this.stackRegion });
|
|
11932
12066
|
delete stateResources[op.logicalId];
|
|
11933
12067
|
this.logger.info(` Rollback: ${op.logicalId} deleted successfully`);
|
|
11934
12068
|
break;
|
|
12069
|
+
}
|
|
11935
12070
|
case "UPDATE": {
|
|
11936
12071
|
if (!op.previousState) {
|
|
11937
12072
|
this.logger.warn(` Rollback: Cannot restore ${op.logicalId} — no previous state available`);
|
|
11938
12073
|
break;
|
|
11939
12074
|
}
|
|
11940
12075
|
this.logger.info(` Rollback: Restoring ${op.logicalId} (${op.resourceType}) to previous state`);
|
|
11941
|
-
const provider = this.providerRegistry.
|
|
12076
|
+
const { provider } = this.providerRegistry.getProviderFor({
|
|
12077
|
+
resourceType: op.resourceType,
|
|
12078
|
+
provisionedBy: op.provisionedBy
|
|
12079
|
+
});
|
|
11942
12080
|
const currentResource = stateResources[op.logicalId];
|
|
11943
12081
|
if (!currentResource) {
|
|
11944
12082
|
this.logger.warn(` Rollback: Cannot restore ${op.logicalId} — resource not found in current state`);
|
|
@@ -11965,7 +12103,7 @@ var DeployEngine = class {
|
|
|
11965
12103
|
const resourceType = change.resourceType;
|
|
11966
12104
|
const renderer = getLiveRenderer();
|
|
11967
12105
|
const needsReplacement = change.changeType === "UPDATE" && (change.propertyChanges?.some((pc) => pc.requiresReplacement) ?? false);
|
|
11968
|
-
const baseLabel = `${change.changeType === "CREATE" ? "Creating" : change.changeType === "DELETE" ? "Deleting" : needsReplacement ? "Replacing" : "Updating"} ${logicalId} (${resourceType})`;
|
|
12106
|
+
const baseLabel = `${change.changeType === "CREATE" ? "Creating" : change.changeType === "DELETE" ? "Deleting" : needsReplacement ? "Replacing" : "Updating"} ${logicalId} (${resourceType})${this.peekRoutingForLabel(change, stateResources[logicalId]) === "cc-api" ? " [CC API]" : ""}`;
|
|
11969
12107
|
renderer.addTask(logicalId, baseLabel);
|
|
11970
12108
|
const operationKind = change.changeType === "CREATE" ? "CREATE" : change.changeType === "DELETE" ? "DELETE" : "UPDATE";
|
|
11971
12109
|
const providerMinTimeoutMs = this.providerRegistry.getProvider(resourceType).getMinResourceTimeoutMs?.() ?? 0;
|
|
@@ -11997,6 +12135,9 @@ var DeployEngine = class {
|
|
|
11997
12135
|
renderer.removeTask(logicalId);
|
|
11998
12136
|
}
|
|
11999
12137
|
}
|
|
12138
|
+
peekRoutingForLabel(change, existingState) {
|
|
12139
|
+
return deriveLabelRouting(change, existingState, this.providerRegistry);
|
|
12140
|
+
}
|
|
12000
12141
|
/**
|
|
12001
12142
|
* Inner body of provisionResource, extracted so the outer wrapper can
|
|
12002
12143
|
* apply the per-resource deadline (`withResourceDeadline`) without
|
|
@@ -12005,7 +12146,7 @@ var DeployEngine = class {
|
|
|
12005
12146
|
*/
|
|
12006
12147
|
async provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress) {
|
|
12007
12148
|
const resourceType = change.resourceType;
|
|
12008
|
-
const
|
|
12149
|
+
const existingState = stateResources[logicalId];
|
|
12009
12150
|
const renderer = getLiveRenderer();
|
|
12010
12151
|
switch (change.changeType) {
|
|
12011
12152
|
case "CREATE": {
|
|
@@ -12017,8 +12158,13 @@ var DeployEngine = class {
|
|
|
12017
12158
|
...conditions && { conditions }
|
|
12018
12159
|
}, stackName);
|
|
12019
12160
|
const resolvedProps = await this.resolver.resolve(desiredProps, context);
|
|
12020
|
-
const
|
|
12021
|
-
|
|
12161
|
+
const createDecision = this.providerRegistry.getProviderFor({
|
|
12162
|
+
resourceType,
|
|
12163
|
+
properties: resolvedProps
|
|
12164
|
+
});
|
|
12165
|
+
const createProvider = createDecision.provider;
|
|
12166
|
+
const createProps = createDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
12167
|
+
const result = await this.withRetry(() => createProvider.create(logicalId, resourceType, createProps), logicalId, void 0, void 0, createProvider);
|
|
12022
12168
|
const dependencies = this.extractAllDependencies(template, logicalId);
|
|
12023
12169
|
const templateAttrs = this.extractTemplateAttributes(template, logicalId);
|
|
12024
12170
|
stateResources[logicalId] = {
|
|
@@ -12027,9 +12173,10 @@ var DeployEngine = class {
|
|
|
12027
12173
|
properties: resolvedProps,
|
|
12028
12174
|
...result.attributes && { attributes: result.attributes },
|
|
12029
12175
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
12030
|
-
...templateAttrs
|
|
12176
|
+
...templateAttrs,
|
|
12177
|
+
provisionedBy: createDecision.provisionedBy
|
|
12031
12178
|
};
|
|
12032
|
-
this.kickOffObservedCapture(
|
|
12179
|
+
this.kickOffObservedCapture(createProvider, logicalId, result.physicalId, resourceType, resolvedProps);
|
|
12033
12180
|
if (counts) counts.created++;
|
|
12034
12181
|
if (progress) progress.current++;
|
|
12035
12182
|
const createPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
@@ -12038,7 +12185,7 @@ var DeployEngine = class {
|
|
|
12038
12185
|
break;
|
|
12039
12186
|
}
|
|
12040
12187
|
case "UPDATE": {
|
|
12041
|
-
const currentResource =
|
|
12188
|
+
const currentResource = existingState;
|
|
12042
12189
|
if (!currentResource) throw new Error(`Cannot update ${logicalId}: resource not found in state`);
|
|
12043
12190
|
const desiredProps = change.desiredProperties || {};
|
|
12044
12191
|
const currentProps = change.currentProperties || {};
|
|
@@ -12073,14 +12220,24 @@ var DeployEngine = class {
|
|
|
12073
12220
|
if (needsReplacement) {
|
|
12074
12221
|
const replacedProps = change.propertyChanges?.filter((pc) => pc.requiresReplacement).map((pc) => pc.path).join(", ");
|
|
12075
12222
|
this.logger.info(`Replacing ${logicalId} (${resourceType}) - immutable properties changed: ${replacedProps}`);
|
|
12223
|
+
const replaceDecision = this.providerRegistry.getProviderFor({
|
|
12224
|
+
resourceType,
|
|
12225
|
+
properties: resolvedProps
|
|
12226
|
+
});
|
|
12227
|
+
const replaceProvider = replaceDecision.provider;
|
|
12228
|
+
const replaceProps = replaceDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
12076
12229
|
this.logger.info(` Creating new ${logicalId}...`);
|
|
12077
|
-
const
|
|
12078
|
-
const
|
|
12079
|
-
|
|
12230
|
+
const createResult = await this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider);
|
|
12231
|
+
const updateReplacePolicy = template?.Resources?.[logicalId]?.UpdateReplacePolicy;
|
|
12232
|
+
const oldDeleteProvider = this.providerRegistry.getProviderFor({
|
|
12233
|
+
resourceType,
|
|
12234
|
+
provisionedBy: currentResource.provisionedBy
|
|
12235
|
+
}).provider;
|
|
12236
|
+
if (updateReplacePolicy === "Retain") this.logger.info(` Retaining old ${logicalId} (${currentResource.physicalId}) - UpdateReplacePolicy: Retain`);
|
|
12080
12237
|
else {
|
|
12081
12238
|
this.logger.info(` Deleting old ${logicalId} (${currentResource.physicalId})...`);
|
|
12082
12239
|
try {
|
|
12083
|
-
await
|
|
12240
|
+
await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, { expectedRegion: this.stackRegion });
|
|
12084
12241
|
this.logger.info(` ${green("✓")} Old resource deleted`);
|
|
12085
12242
|
} catch (deleteError) {
|
|
12086
12243
|
this.logger.warn(` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
|
|
@@ -12092,9 +12249,10 @@ var DeployEngine = class {
|
|
|
12092
12249
|
properties: resolvedProps,
|
|
12093
12250
|
...createResult.attributes && { attributes: createResult.attributes },
|
|
12094
12251
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
12095
|
-
...this.extractTemplateAttributes(template, logicalId)
|
|
12252
|
+
...this.extractTemplateAttributes(template, logicalId),
|
|
12253
|
+
provisionedBy: replaceDecision.provisionedBy
|
|
12096
12254
|
};
|
|
12097
|
-
this.kickOffObservedCapture(
|
|
12255
|
+
this.kickOffObservedCapture(replaceProvider, logicalId, createResult.physicalId, resourceType, resolvedProps);
|
|
12098
12256
|
if (counts) counts.updated++;
|
|
12099
12257
|
if (progress) progress.current++;
|
|
12100
12258
|
const replacePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
@@ -12102,28 +12260,41 @@ var DeployEngine = class {
|
|
|
12102
12260
|
this.logger.info(`${replacePrefix}${yellow("↻")} ${bold(logicalId)} ${gray(`(${resourceType})`)} ${yellow("replaced")}`);
|
|
12103
12261
|
} else {
|
|
12104
12262
|
this.logger.debug(`Updating ${logicalId} (${resourceType})`);
|
|
12105
|
-
const
|
|
12263
|
+
const updateDecision = this.providerRegistry.getProviderFor({
|
|
12264
|
+
resourceType,
|
|
12265
|
+
properties: resolvedProps,
|
|
12266
|
+
provisionedBy: currentResource.provisionedBy
|
|
12267
|
+
});
|
|
12268
|
+
const updateProvider = updateDecision.provider;
|
|
12269
|
+
const updateProps = updateDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
12106
12270
|
let result;
|
|
12271
|
+
let resultProvisionedBy = updateDecision.provisionedBy;
|
|
12107
12272
|
try {
|
|
12108
|
-
result = await this.withRetry(() => updateProvider.update(logicalId, currentResource.physicalId, resourceType, updateProps, currentProps), logicalId, void 0, void 0,
|
|
12273
|
+
result = await this.withRetry(() => updateProvider.update(logicalId, currentResource.physicalId, resourceType, updateProps, currentProps), logicalId, void 0, void 0, updateProvider);
|
|
12109
12274
|
} catch (updateError) {
|
|
12110
12275
|
const msg = updateError instanceof Error ? updateError.message : String(updateError);
|
|
12111
12276
|
if (msg.includes("UnsupportedActionException") || msg.includes("does not support UPDATE")) {
|
|
12112
12277
|
this.logger.info(`UPDATE not supported for ${logicalId} (${resourceType}), replacing (DELETE → CREATE)`);
|
|
12113
12278
|
try {
|
|
12114
|
-
await
|
|
12279
|
+
await updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, { expectedRegion: this.stackRegion });
|
|
12115
12280
|
} catch (deleteError) {
|
|
12116
12281
|
const deleteMsg = deleteError instanceof Error ? deleteError.message : String(deleteError);
|
|
12117
12282
|
if (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound")) this.logger.debug(`Old resource ${logicalId} already gone, proceeding with CREATE`);
|
|
12118
12283
|
else throw deleteError;
|
|
12119
12284
|
}
|
|
12120
|
-
const
|
|
12121
|
-
|
|
12285
|
+
const replDecision = this.providerRegistry.getProviderFor({
|
|
12286
|
+
resourceType,
|
|
12287
|
+
properties: resolvedProps
|
|
12288
|
+
});
|
|
12289
|
+
const replProvider = replDecision.provider;
|
|
12290
|
+
const replProps = replDecision.provisionedBy === "cc-api" ? this.preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) : resolvedProps;
|
|
12291
|
+
const createResult = await this.withRetry(() => replProvider.create(logicalId, resourceType, replProps), logicalId, void 0, void 0, replProvider);
|
|
12122
12292
|
result = {
|
|
12123
12293
|
physicalId: createResult.physicalId,
|
|
12124
12294
|
attributes: createResult.attributes,
|
|
12125
12295
|
wasReplaced: true
|
|
12126
12296
|
};
|
|
12297
|
+
resultProvisionedBy = replDecision.provisionedBy;
|
|
12127
12298
|
} else throw updateError;
|
|
12128
12299
|
}
|
|
12129
12300
|
if (result.wasReplaced) this.logger.info(`Resource ${logicalId} was replaced: ${currentResource.physicalId} -> ${result.physicalId}`);
|
|
@@ -12133,9 +12304,10 @@ var DeployEngine = class {
|
|
|
12133
12304
|
properties: resolvedProps,
|
|
12134
12305
|
...result.attributes && { attributes: result.attributes },
|
|
12135
12306
|
...dependencies && dependencies.length > 0 && { dependencies },
|
|
12136
|
-
...this.extractTemplateAttributes(template, logicalId)
|
|
12307
|
+
...this.extractTemplateAttributes(template, logicalId),
|
|
12308
|
+
provisionedBy: resultProvisionedBy
|
|
12137
12309
|
};
|
|
12138
|
-
this.kickOffObservedCapture(
|
|
12310
|
+
this.kickOffObservedCapture(updateProvider, logicalId, result.physicalId, resourceType, resolvedProps);
|
|
12139
12311
|
if (counts) counts.updated++;
|
|
12140
12312
|
if (progress) progress.current++;
|
|
12141
12313
|
const updatePrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
|
|
@@ -12145,7 +12317,7 @@ var DeployEngine = class {
|
|
|
12145
12317
|
break;
|
|
12146
12318
|
}
|
|
12147
12319
|
case "DELETE": {
|
|
12148
|
-
const currentResource =
|
|
12320
|
+
const currentResource = existingState;
|
|
12149
12321
|
if (!currentResource) throw new Error(`Cannot delete ${logicalId}: resource not found in state`);
|
|
12150
12322
|
const deletionPolicy = currentResource.deletionPolicy ?? template?.Resources?.[logicalId]?.DeletionPolicy;
|
|
12151
12323
|
if (shouldRetainResource(deletionPolicy)) {
|
|
@@ -12153,9 +12325,13 @@ var DeployEngine = class {
|
|
|
12153
12325
|
delete stateResources[logicalId];
|
|
12154
12326
|
break;
|
|
12155
12327
|
}
|
|
12328
|
+
const deleteProvider = this.providerRegistry.getProviderFor({
|
|
12329
|
+
resourceType,
|
|
12330
|
+
provisionedBy: currentResource.provisionedBy
|
|
12331
|
+
}).provider;
|
|
12156
12332
|
this.logger.debug(`Deleting ${logicalId} (${resourceType})`);
|
|
12157
12333
|
try {
|
|
12158
|
-
await this.withRetry(() =>
|
|
12334
|
+
await this.withRetry(() => deleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, { expectedRegion: this.stackRegion }), logicalId, 3, 5e3, deleteProvider);
|
|
12159
12335
|
} catch (deleteError) {
|
|
12160
12336
|
const msg = deleteError instanceof Error ? deleteError.message : String(deleteError);
|
|
12161
12337
|
if (msg.includes("does not exist") || msg.includes("was not found") || msg.includes("not found") || msg.includes("No policy found") || msg.includes("NoSuchEntity") || msg.includes("NotFoundException") || msg.includes("ResourceNotFoundException")) this.logger.debug(`Resource ${logicalId} already deleted (${msg}), removing from state`);
|
|
@@ -12279,35 +12455,23 @@ var DeployEngine = class {
|
|
|
12279
12455
|
}
|
|
12280
12456
|
}
|
|
12281
12457
|
/**
|
|
12282
|
-
*
|
|
12283
|
-
*
|
|
12284
|
-
*
|
|
12285
|
-
*
|
|
12286
|
-
*
|
|
12458
|
+
* Prepare a property map for a Cloud Control API call. When a Tier 1
|
|
12459
|
+
* resource is routed via Cloud Control (either because the user's
|
|
12460
|
+
* template hit silent-drop properties under #614 or because the resource
|
|
12461
|
+
* is sticky-routed via `provisionedBy: 'cc-api'`), CC requires the full
|
|
12462
|
+
* property map — including identifier-like fields (`BucketName`,
|
|
12463
|
+
* `RoleName`, etc.) that the SDK provider would have auto-generated.
|
|
12464
|
+
* This helper threads the property prep through the registered SDK
|
|
12465
|
+
* provider's `preparePropertiesForFallback` hook when defined, falling
|
|
12466
|
+
* back to `applyDefaultNameForFallback` (which mints stack-prefixed
|
|
12467
|
+
* names matching what the SDK provider would have done) otherwise.
|
|
12287
12468
|
*
|
|
12288
|
-
*
|
|
12469
|
+
* No-ops for types with no registered SDK provider (Tier 2 / CC-native).
|
|
12289
12470
|
*/
|
|
12290
|
-
|
|
12291
|
-
const
|
|
12292
|
-
if (
|
|
12293
|
-
|
|
12294
|
-
properties: resolvedProps
|
|
12295
|
-
};
|
|
12296
|
-
const unhandledProps = Object.keys(resolvedProps).filter((p) => !handledSet.has(p));
|
|
12297
|
-
if (unhandledProps.length === 0) return {
|
|
12298
|
-
provider: sdkProvider,
|
|
12299
|
-
properties: resolvedProps
|
|
12300
|
-
};
|
|
12301
|
-
if (CloudControlProvider.isSupportedResourceType(resourceType) && !sdkProvider.disableCcApiFallback) {
|
|
12302
|
-
this.logger.info(`${logicalId}: SDK provider does not handle [${unhandledProps.join(", ")}] — falling back to CC API for create/update`);
|
|
12303
|
-
const fallbackProps = sdkProvider.preparePropertiesForFallback ? sdkProvider.preparePropertiesForFallback(logicalId, resourceType, resolvedProps) : applyDefaultNameForFallback(logicalId, resourceType, resolvedProps);
|
|
12304
|
-
return {
|
|
12305
|
-
provider: this.providerRegistry.getCloudControlProvider(),
|
|
12306
|
-
properties: fallbackProps
|
|
12307
|
-
};
|
|
12308
|
-
}
|
|
12309
|
-
const reason = sdkProvider.disableCcApiFallback ? "CC API fallback is disabled for this provider (known CC API issues)" : `CC API does not support ${resourceType}`;
|
|
12310
|
-
throw new ProvisioningError(`SDK provider for ${resourceType} does not handle properties [${unhandledProps.join(", ")}] and ${reason}. These properties would be silently dropped. Please update the SDK provider to handle all required properties.`, resourceType, logicalId, "");
|
|
12471
|
+
preparePropertiesForCcApi(resourceType, resolvedProps, logicalId) {
|
|
12472
|
+
const sdkProvider = this.providerRegistry.getRegisteredTypes().includes(resourceType) ? this.providerRegistry.getProvider(resourceType) : void 0;
|
|
12473
|
+
if (sdkProvider?.preparePropertiesForFallback) return sdkProvider.preparePropertiesForFallback(logicalId, resourceType, resolvedProps);
|
|
12474
|
+
return applyDefaultNameForFallback(logicalId, resourceType, resolvedProps);
|
|
12311
12475
|
}
|
|
12312
12476
|
/**
|
|
12313
12477
|
* Execute an operation with retry for transient IAM propagation errors.
|
|
@@ -12372,5 +12536,5 @@ var DeployEngine = class {
|
|
|
12372
12536
|
};
|
|
12373
12537
|
|
|
12374
12538
|
//#endregion
|
|
12375
|
-
export {
|
|
12376
|
-
//# sourceMappingURL=deploy-engine-
|
|
12539
|
+
export { AssetError as $, S3StateBackend as A, resolveCaptureObservedState as B, assertRegionMatch as C, DagBuilder as D, DiffCalculator as E, buildDockerImage as F, CFN_TEMPLATE_BODY_LIMIT as G, resolveStateBucketWithDefault as H, Synthesizer as I, findLargeInlineResources as J, CFN_TEMPLATE_URL_LIMIT as K, getDefaultStateBucketName as L, AssetPublisher as M, stringifyValue as N, TemplateParser as O, WorkGraph as P, resolveBucketRegion as Q, getLegacyStateBucketName as R, CloudControlProvider as S, applyRoleArnIfSet as T, resolveStateBucketWithDefaultAndSource as U, resolveSkipPrefix as V, warnDeprecatedNoPrefixCliFlag as W, AssemblyReader as X, uploadCfnTemplate as Y, clearBucketRegionCache as Z, matchesCdkPath as _, SynthesisError as _t, withRetry as a, LocalStartServiceError as at, ProviderRegistry as b, normalizeAwsError as bt, bold as c, NestedStackChildDirectDestroyError as ct, green as d, ResourceTimeoutError as dt, CdkdError as et, red as f, ResourceUpdateNotSupportedError as ft, CDK_PATH_TAG as g, StateError as gt, collectInlinePolicyNamesManagedBySiblings as h, StackTerminationProtectionError as ht, withResourceDeadline as i, LocalMigrateError as it, shouldRetainResource as j, LockManager as k, cyan as l, PartialFailureError as lt, IAMRoleProvider as m, StackHasActiveImportsError as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, DependencyError as nt, IMPLICIT_DELETE_DEPENDENCIES as o, LockError as ot, yellow as p, RouteDiscoveryError as pt, MIGRATE_TMP_PREFIX as q, DeployEngine as r, LocalInvokeBuildError as rt, formatResourceLine as s, MissingCdkCliError as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, ConfigError as tt, gray as u, ProvisioningError as ut, normalizeAwsTagsToCfn as v, formatError as vt, IntrinsicFunctionResolver as w, findActionableSilentDrops as x, withErrorHandling as xt, resolveExplicitPhysicalId as y, isCdkdError as yt, resolveApp as z };
|
|
12540
|
+
//# sourceMappingURL=deploy-engine-BC1Z7ABm.js.map
|