@go-to-k/cdkd 0.278.22 → 0.278.23
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/{asg-provider-BBsW05cu.js → asg-provider-ir7DmsIU.js} +2 -2
- package/dist/{asg-provider-BBsW05cu.js.map → asg-provider-ir7DmsIU.js.map} +1 -1
- package/dist/cli.js +212 -26
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-CkuG2VD5.js → deploy-engine-D7KckQ5N.js} +52 -6
- package/dist/{deploy-engine-CkuG2VD5.js.map → deploy-engine-D7KckQ5N.js.map} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as isThrottlingError, $t as setAwsClients, A as red, At as getLegacyStateBucketName, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_BODY_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerForeground, D as cyan, Dt as Synthesizer, E as bold, Et as getDockerImageBySourceHash, F as ProviderRegistry, Ft as resolveStateBucketWithDefault, G as normalizeAwsTagsToCfn, Gt as expectedOwnerParam, H as cfnRefValueFromPhysicalId, Ht as MIGRATE_TMP_PREFIX, I as findActionableSilentDrops, It as resolveStateBucketWithDefaultAndSource, J as applyRoleArnIfSet, K as resolveExplicitPhysicalId, Kt as AssemblyReader, L as CloudControlProvider, Lt as resolveUseCdkBootstrapAssets, M as IAMRoleProvider, Mt as resolveAutoAssetStorage, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveCaptureObservedState, O as gray, Ot as synthesisStatusMessage, P as clearOnUpdateRemoval, Pt as resolveSkipPrefix, Q as isRetryableTransientError, Qt as resetAwsClients, R as slowCcOperationTimeoutMs, Rt as stateBucketExistenceConfirmed, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as withErrorHandling, St as getDockerCmd, T as formatResourceLine, Tt as AssetManifestLoader, U as refStateLookupFromResource, Ut as findLargeInlineResources, V as IntrinsicFunctionResolver, Vt as CFN_TEMPLATE_URL_LIMIT, W as WAFv2WebACLProvider, Wt as uploadCfnTemplate, X as describeTypeWithThrottleRetry, Xt as AwsClients, Y as DiffCalculator, Yt as resolveBucketRegion, Z as withRetry, Zt as getAwsClients, _ as createPreDeleteFinalSnapshot, _t as parseBootstrapMarker, a as DeploymentEventsStore, an as LocalInvokeBuildError$1, at as shouldRetainResource, b as unsupportedFinalSnapshotError, bt as buildDockerImage, c as replayFailedOperations, ct as WorkGraph, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PartialFailureError, dt as loadPublishableAssetManifest, et as DagBuilder, f as computeImplicitDeleteEdges, fn as ProvisioningError, ft as rewriteTemplateAssetReferences, g as ccRoutedFinalSnapshotError, gn as StackTerminationProtectionError, gt as getBootstrapMarkerKey, h as buildFinalSnapshotIdentifier, hn as StackHasActiveImportsError, ht as ensureAssetStorage, i as DeploymentEventsReader, in as DeployCancelledError, it as rebuildClientForBucketRegion, j as yellow, jt as resolveApp, k as green, kt as getDefaultStateBucketName, l as replayRollback, ln as MissingCdkCliError, lt as buildAssetRedirectMap, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ResourceUpdateNotSupportedError, mt as BOOTSTRAP_MARKER_PREFIX, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LockManager, o as planFailedOps, on as LocalMigrateError, ot as AssetPublisher, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceTimeoutError, pt as AssetModeResolver, q as assertRegionMatch, qt as processStackMessages, r as DeployEngine, rt as S3StateBackend, s as planRollback, sn as LocalStartServiceError, st as stringifyValue, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as CdkdError, tt as TemplateParser, u as withResourceDeadline, un as NestedStackChildDirectDestroyError, ut as createAssetRedirectResolver, v as isFinalSnapshotError, vt as validateAssetBucketName, w as renderStatefulReason, wt as runDockerStreaming, x as extractDeploymentEventError, xn as normalizeAwsError, xt as formatDockerLoginError, y as refusesFinalSnapshot, yt as validateContainerRepoName, z as disableInstanceApiTermination, zt as warnDeprecatedNoPrefixCliFlag } from "./deploy-engine-
|
|
2
|
+
import { $ as isThrottlingError, $t as setAwsClients, A as red, At as getLegacyStateBucketName, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_BODY_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerForeground, D as cyan, Dt as Synthesizer, E as bold, Et as getDockerImageBySourceHash, F as ProviderRegistry, Ft as resolveStateBucketWithDefault, G as normalizeAwsTagsToCfn, Gt as expectedOwnerParam, H as cfnRefValueFromPhysicalId, Ht as MIGRATE_TMP_PREFIX, I as findActionableSilentDrops, It as resolveStateBucketWithDefaultAndSource, J as applyRoleArnIfSet, K as resolveExplicitPhysicalId, Kt as AssemblyReader, L as CloudControlProvider, Lt as resolveUseCdkBootstrapAssets, M as IAMRoleProvider, Mt as resolveAutoAssetStorage, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveCaptureObservedState, O as gray, Ot as synthesisStatusMessage, P as clearOnUpdateRemoval, Pt as resolveSkipPrefix, Q as isRetryableTransientError, Qt as resetAwsClients, R as slowCcOperationTimeoutMs, Rt as stateBucketExistenceConfirmed, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as withErrorHandling, St as getDockerCmd, T as formatResourceLine, Tt as AssetManifestLoader, U as refStateLookupFromResource, Ut as findLargeInlineResources, V as IntrinsicFunctionResolver, Vt as CFN_TEMPLATE_URL_LIMIT, W as WAFv2WebACLProvider, Wt as uploadCfnTemplate, X as describeTypeWithThrottleRetry, Xt as AwsClients, Y as DiffCalculator, Yt as resolveBucketRegion, Z as withRetry, Zt as getAwsClients, _ as createPreDeleteFinalSnapshot, _t as parseBootstrapMarker, a as DeploymentEventsStore, an as LocalInvokeBuildError$1, at as shouldRetainResource, b as unsupportedFinalSnapshotError, bt as buildDockerImage, c as replayFailedOperations, ct as WorkGraph, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PartialFailureError, dt as loadPublishableAssetManifest, et as DagBuilder, f as computeImplicitDeleteEdges, fn as ProvisioningError, ft as rewriteTemplateAssetReferences, g as ccRoutedFinalSnapshotError, gn as StackTerminationProtectionError, gt as getBootstrapMarkerKey, h as buildFinalSnapshotIdentifier, hn as StackHasActiveImportsError, ht as ensureAssetStorage, i as DeploymentEventsReader, in as DeployCancelledError, it as rebuildClientForBucketRegion, j as yellow, jt as resolveApp, k as green, kt as getDefaultStateBucketName, l as replayRollback, ln as MissingCdkCliError, lt as buildAssetRedirectMap, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ResourceUpdateNotSupportedError, mt as BOOTSTRAP_MARKER_PREFIX, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LockManager, o as planFailedOps, on as LocalMigrateError, ot as AssetPublisher, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceTimeoutError, pt as AssetModeResolver, q as assertRegionMatch, qt as processStackMessages, r as DeployEngine, rt as S3StateBackend, s as planRollback, sn as LocalStartServiceError, st as stringifyValue, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as CdkdError, tt as TemplateParser, u as withResourceDeadline, un as NestedStackChildDirectDestroyError, ut as createAssetRedirectResolver, v as isFinalSnapshotError, vt as validateAssetBucketName, w as renderStatefulReason, wt as runDockerStreaming, x as extractDeploymentEventError, xn as normalizeAwsError, xt as formatDockerLoginError, y as refusesFinalSnapshot, yt as validateContainerRepoName, z as disableInstanceApiTermination, zt as warnDeprecatedNoPrefixCliFlag } from "./deploy-engine-D7KckQ5N.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-ir7DmsIU.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -52,7 +52,7 @@ import { AddCustomAttributesCommand, CognitoIdentityProviderClient, CreateUserPo
|
|
|
52
52
|
import { CreateHttpNamespaceCommand, CreatePrivateDnsNamespaceCommand, CreatePublicDnsNamespaceCommand, CreateServiceCommand as CreateServiceCommand$1, DeleteNamespaceCommand, DeleteServiceAttributesCommand, DeleteServiceCommand as DeleteServiceCommand$1, GetNamespaceCommand, GetOperationCommand, GetServiceAttributesCommand, GetServiceCommand, ListNamespacesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$14, NamespaceNotFound, ServiceDiscoveryClient, ServiceNotFound, TagResourceCommand as TagResourceCommand$15, UntagResourceCommand as UntagResourceCommand$15, UpdateHttpNamespaceCommand, UpdatePrivateDnsNamespaceCommand, UpdatePublicDnsNamespaceCommand, UpdateServiceAttributesCommand, UpdateServiceCommand as UpdateServiceCommand$1 } from "@aws-sdk/client-servicediscovery";
|
|
53
53
|
import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGraphqlApiCommand, CreateResolverCommand, DeleteApiKeyCommand, DeleteDataSourceCommand, DeleteGraphqlApiCommand, DeleteResolverCommand, GetDataSourceCommand, GetGraphqlApiCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, NotFoundException as NotFoundException$4, StartSchemaCreationCommand, TagResourceCommand as TagResourceCommand$16, UntagResourceCommand as UntagResourceCommand$16, UpdateApiKeyCommand, UpdateDataSourceCommand, UpdateGraphqlApiCommand, UpdateResolverCommand } from "@aws-sdk/client-appsync";
|
|
54
54
|
import { parse, print } from "graphql";
|
|
55
|
-
import { CrawlerRunningException, CreateConnectionCommand, CreateCrawlerCommand, CreateDatabaseCommand, CreateJobCommand, CreateSecurityConfigurationCommand, CreateTableCommand as CreateTableCommand$1, CreateTriggerCommand, CreateWorkflowCommand, DeleteConnectionCommand, DeleteCrawlerCommand, DeleteDatabaseCommand, DeleteJobCommand, DeleteSecurityConfigurationCommand, DeleteTableCommand as DeleteTableCommand$1, DeleteTriggerCommand, DeleteWorkflowCommand, EntityNotFoundException, GetConnectionCommand, GetCrawlerCommand, GetDatabaseCommand, GetJobCommand, GetSecurityConfigurationCommand, GetTableCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
|
|
55
|
+
import { ConcurrentModificationException, CrawlerRunningException, CreateConnectionCommand, CreateCrawlerCommand, CreateDatabaseCommand, CreateJobCommand, CreateSecurityConfigurationCommand, CreateTableCommand as CreateTableCommand$1, CreateTriggerCommand, CreateWorkflowCommand, DeleteConnectionCommand, DeleteCrawlerCommand, DeleteDatabaseCommand, DeleteJobCommand, DeleteSecurityConfigurationCommand, DeleteTableCommand as DeleteTableCommand$1, DeleteTriggerCommand, DeleteWorkflowCommand, EntityNotFoundException, GetConnectionCommand, GetCrawlerCommand, GetDatabaseCommand, GetJobCommand, GetSecurityConfigurationCommand, GetTableCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
|
|
56
56
|
import { BudgetsClient, CreateBudgetCommand, CreateNotificationCommand, CreateSubscriberCommand, DeleteBudgetCommand, DeleteNotificationCommand, DeleteSubscriberCommand, DescribeBudgetCommand, DuplicateRecordException, NotFoundException as NotFoundException$5, TagResourceCommand as TagResourceCommand$17, UntagResourceCommand as UntagResourceCommand$17, UpdateBudgetCommand } from "@aws-sdk/client-budgets";
|
|
57
57
|
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, DescribeStreamSummaryCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListTagsForResourceCommand as ListTagsForResourceCommand$15, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$10, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$18, UntagResourceCommand as UntagResourceCommand$18, UpdateShardCountCommand, UpdateStreamModeCommand } from "@aws-sdk/client-kinesis";
|
|
58
58
|
import { CreateScheduleCommand, DeleteScheduleCommand, GetScheduleCommand, ResourceNotFoundException as ResourceNotFoundException$11, SchedulerClient, UpdateScheduleCommand } from "@aws-sdk/client-scheduler";
|
|
@@ -33046,10 +33046,10 @@ var GlueProvider = class {
|
|
|
33046
33046
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
|
|
33047
33047
|
}
|
|
33048
33048
|
}
|
|
33049
|
-
async update(logicalId, physicalId, resourceType, properties,
|
|
33049
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
33050
33050
|
switch (resourceType) {
|
|
33051
|
-
case "AWS::Glue::Database": return this.updateDatabase(logicalId, physicalId, resourceType, properties);
|
|
33052
|
-
case "AWS::Glue::Table": return this.updateTable(logicalId, physicalId, resourceType, properties);
|
|
33051
|
+
case "AWS::Glue::Database": return this.updateDatabase(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
33052
|
+
case "AWS::Glue::Table": return this.updateTable(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
33053
33053
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
33054
33054
|
}
|
|
33055
33055
|
}
|
|
@@ -33082,16 +33082,19 @@ var GlueProvider = class {
|
|
|
33082
33082
|
throw new ProvisioningError(`Failed to create Glue Database ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
33083
33083
|
}
|
|
33084
33084
|
}
|
|
33085
|
-
async updateDatabase(logicalId, physicalId, resourceType, properties) {
|
|
33085
|
+
async updateDatabase(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
33086
33086
|
this.logger.debug(`Updating Glue Database ${logicalId}: ${physicalId}`);
|
|
33087
33087
|
const databaseInput = properties["DatabaseInput"];
|
|
33088
33088
|
if (!databaseInput) throw new ProvisioningError(`DatabaseInput is required for Glue Database update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
33089
33089
|
const catalogId = properties["CatalogId"];
|
|
33090
|
+
const liveParameters = await this.readLiveDatabaseParameters(logicalId, resourceType, physicalId, catalogId);
|
|
33090
33091
|
try {
|
|
33092
|
+
const builtDatabaseInput = this.buildDatabaseInput(databaseInput, physicalId);
|
|
33093
|
+
this.preserveAwsManagedParameters(builtDatabaseInput, databaseInput["Parameters"], (previousProperties?.["DatabaseInput"])?.["Parameters"], liveParameters);
|
|
33091
33094
|
await this.getClient().send(new UpdateDatabaseCommand({
|
|
33092
33095
|
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33093
33096
|
Name: physicalId,
|
|
33094
|
-
DatabaseInput:
|
|
33097
|
+
DatabaseInput: builtDatabaseInput
|
|
33095
33098
|
}));
|
|
33096
33099
|
this.logger.debug(`Successfully updated Glue Database ${logicalId}`);
|
|
33097
33100
|
return {
|
|
@@ -33151,7 +33154,7 @@ var GlueProvider = class {
|
|
|
33151
33154
|
throw new ProvisioningError(`Failed to create Glue Table ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
33152
33155
|
}
|
|
33153
33156
|
}
|
|
33154
|
-
async updateTable(logicalId, physicalId, resourceType, properties) {
|
|
33157
|
+
async updateTable(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
33155
33158
|
this.logger.debug(`Updating Glue Table ${logicalId}: ${physicalId}`);
|
|
33156
33159
|
const [databaseName, tableName] = physicalId.split("|");
|
|
33157
33160
|
if (!databaseName || !tableName) throw new ProvisioningError(`Invalid Glue Table physical ID format: ${physicalId}`, resourceType, logicalId, physicalId);
|
|
@@ -33160,11 +33163,15 @@ var GlueProvider = class {
|
|
|
33160
33163
|
const catalogId = properties["CatalogId"];
|
|
33161
33164
|
const updateIcebergKey = findIcebergTableInputKey(properties);
|
|
33162
33165
|
if (updateIcebergKey !== void 0) this.logger.warn(icebergTableInputRefusalMessage(logicalId, updateIcebergKey, "update"));
|
|
33166
|
+
const live = await this.readLiveTableState(logicalId, resourceType, physicalId, databaseName, tableName, catalogId);
|
|
33163
33167
|
try {
|
|
33168
|
+
const builtTableInput = this.buildTableInput(tableInput, tableName);
|
|
33169
|
+
this.preserveAwsManagedParameters(builtTableInput, tableInput["Parameters"], (previousProperties?.["TableInput"])?.["Parameters"], live.parameters);
|
|
33164
33170
|
await this.getClient().send(new UpdateTableCommand$1({
|
|
33165
|
-
CatalogId: catalogId,
|
|
33171
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33166
33172
|
DatabaseName: databaseName,
|
|
33167
|
-
TableInput:
|
|
33173
|
+
TableInput: builtTableInput,
|
|
33174
|
+
...live.versionId !== void 0 && { VersionId: live.versionId }
|
|
33168
33175
|
}));
|
|
33169
33176
|
this.logger.debug(`Successfully updated Glue Table ${logicalId}`);
|
|
33170
33177
|
return {
|
|
@@ -33173,7 +33180,13 @@ var GlueProvider = class {
|
|
|
33173
33180
|
};
|
|
33174
33181
|
} catch (error) {
|
|
33175
33182
|
const cause = error instanceof Error ? error : void 0;
|
|
33176
|
-
|
|
33183
|
+
let message = `Failed to update Glue Table ${logicalId}: ${error instanceof Error ? error.message : String(error)}`;
|
|
33184
|
+
if (error instanceof ConcurrentModificationException) {
|
|
33185
|
+
message += ". Another writer changed the table between cdkd's pre-update read and its UpdateTable call.";
|
|
33186
|
+
message += live.versionId !== void 0 ? ` cdkd sent the version it read (${live.versionId}) as a precondition and AWS rejected the write, rather than let it put back the AWS-managed Parameters read a moment earlier — which for an Apache Iceberg table would have pinned it to an older metadata_location (an effective snapshot rollback).` : " AWS returned no VersionId on the pre-update read, so cdkd could not attach a precondition; AWS rejected the write on its own.";
|
|
33187
|
+
message += ` Re-run the deploy to pick up the current values.`;
|
|
33188
|
+
}
|
|
33189
|
+
throw new ProvisioningError(message, resourceType, logicalId, physicalId, cause);
|
|
33177
33190
|
}
|
|
33178
33191
|
}
|
|
33179
33192
|
async deleteTable(logicalId, physicalId, resourceType, _properties, context) {
|
|
@@ -33200,6 +33213,150 @@ var GlueProvider = class {
|
|
|
33200
33213
|
}
|
|
33201
33214
|
}
|
|
33202
33215
|
/**
|
|
33216
|
+
* Merge AWS-AUTHORED `Parameters` back into a full-replace update payload
|
|
33217
|
+
* (issue [#1461](https://github.com/go-to-k/cdkd/issues/1461)).
|
|
33218
|
+
*
|
|
33219
|
+
* `UpdateTable` / `UpdateDatabase` replace `TableInput` / `DatabaseInput`
|
|
33220
|
+
* **wholesale**: whatever the payload omits is erased. `Parameters` is a
|
|
33221
|
+
* general-purpose bag that AWS itself writes into, so keys with NO template
|
|
33222
|
+
* representation were wiped by the first unrelated edit. For an Apache
|
|
33223
|
+
* Iceberg table that is not cosmetic — `table_type: ICEBERG` and
|
|
33224
|
+
* `metadata_location` are what make the table readable as Iceberg by
|
|
33225
|
+
* Athena / Spark / EMR, and losing them silently degrades it to a plain
|
|
33226
|
+
* external table pointing at Iceberg data files. Verified live 2026-08-10
|
|
33227
|
+
* in us-east-1: a deploy changing only `TableInput.Description` left
|
|
33228
|
+
* `Table.Parameters` as `null`. The same exposure covers a Glue crawler's
|
|
33229
|
+
* `classification`, `EXTERNAL`, `comment`, and Lake Formation markers.
|
|
33230
|
+
*
|
|
33231
|
+
* The merge is keyed on **"present in NEITHER template side"**, not on
|
|
33232
|
+
* "absent from the desired side" — the latter would make user-authored
|
|
33233
|
+
* parameters unremovable, i.e. the mirror image of the bug:
|
|
33234
|
+
*
|
|
33235
|
+
* | key in desired | key in previous | outcome |
|
|
33236
|
+
* | -------------- | --------------- | ------------------------------------ |
|
|
33237
|
+
* | yes | (either) | the user's value wins |
|
|
33238
|
+
* | no | yes | the USER REMOVED it -> stays removed |
|
|
33239
|
+
* | no | no | AWS-AUTHORED -> preserved from live |
|
|
33240
|
+
*
|
|
33241
|
+
* That keeps this provider on the repo's established clear-on-removal
|
|
33242
|
+
* position (docs/provider-development.md §2a, issue #1155): a removal the
|
|
33243
|
+
* user expressed in the template still reaches AWS. Glue's update APIs are
|
|
33244
|
+
* full-replace, so removal needs no explicit reset sentinel — omitting the
|
|
33245
|
+
* key IS the reset, and the only thing this helper adds back is the set of
|
|
33246
|
+
* keys the user never authored in the first place. The generalized rule for
|
|
33247
|
+
* any full-replace update API lives in docs/provider-development.md §2b.
|
|
33248
|
+
*
|
|
33249
|
+
* Audited siblings that do NOT get this treatment: `JobUpdate`'s
|
|
33250
|
+
* `DefaultArguments` / `NonOverridableArguments`, `ConnectionInput`'s
|
|
33251
|
+
* `ConnectionProperties`, `WorkflowUpdate.DefaultRunProperties` and
|
|
33252
|
+
* `Crawler.Configuration` are purely USER-authored bags — AWS does not
|
|
33253
|
+
* write into them, so merging live values back would only resurrect
|
|
33254
|
+
* console-side additions and break `cdkd drift --revert`.
|
|
33255
|
+
*
|
|
33256
|
+
* `desiredParameters` / `previousParameters` are the raw CFn-side maps
|
|
33257
|
+
* (their KEY SET is all that matters here; `buildTableInput` already
|
|
33258
|
+
* stringified the desired VALUES into `built.Parameters`).
|
|
33259
|
+
*/
|
|
33260
|
+
preserveAwsManagedParameters(built, desiredParameters, previousParameters, liveParameters) {
|
|
33261
|
+
if (!liveParameters || Object.keys(liveParameters).length === 0) return;
|
|
33262
|
+
const desiredKeys = parameterKeySet(desiredParameters);
|
|
33263
|
+
const previousKeys = parameterKeySet(previousParameters);
|
|
33264
|
+
const awsAuthored = {};
|
|
33265
|
+
for (const [key, value] of Object.entries(liveParameters)) {
|
|
33266
|
+
if (desiredKeys.has(key) || previousKeys.has(key)) continue;
|
|
33267
|
+
awsAuthored[key] = value;
|
|
33268
|
+
}
|
|
33269
|
+
if (Object.keys(awsAuthored).length === 0) return;
|
|
33270
|
+
built.Parameters = {
|
|
33271
|
+
...awsAuthored,
|
|
33272
|
+
...built.Parameters ?? {}
|
|
33273
|
+
};
|
|
33274
|
+
}
|
|
33275
|
+
/**
|
|
33276
|
+
* The live table state {@link preserveAwsManagedParameters} needs: its
|
|
33277
|
+
* current `Parameters` plus the `VersionId` that pins them.
|
|
33278
|
+
*
|
|
33279
|
+
* A missing table returns empty rather than throwing: `UpdateTable` is about
|
|
33280
|
+
* to surface the real, more actionable error. Any OTHER failure is fatal by
|
|
33281
|
+
* design — degrading to "skip the merge" would silently reinstate the very
|
|
33282
|
+
* wipe this read exists to prevent, and the wrapped cause keeps a transient
|
|
33283
|
+
* throttle retryable by the deploy engine's outer `withRetry` (every
|
|
33284
|
+
* `provider.update()` call site wraps it, including both rollback arms since
|
|
33285
|
+
* this issue).
|
|
33286
|
+
*
|
|
33287
|
+
* **Why `VersionId` matters and why it is SCOPED.** Reading `Parameters`
|
|
33288
|
+
* here and writing them back in the next call opens a TOCTOU window: an
|
|
33289
|
+
* Apache Iceberg commit from Spark / Athena / EMR landing in between would
|
|
33290
|
+
* be undone by writing back the `metadata_location` we read, pinning the
|
|
33291
|
+
* table to an older snapshot — silent data-visibility loss, strictly worse
|
|
33292
|
+
* than the bug this read fixes. `UpdateTableRequest.VersionId` is AWS's
|
|
33293
|
+
* optimistic-concurrency token for exactly this
|
|
33294
|
+
* (`ConcurrentModificationException` is a documented `UpdateTable` error),
|
|
33295
|
+
* so the caller sends the version it read and a concurrent commit makes the
|
|
33296
|
+
* update fail loudly instead of silently rolling back.
|
|
33297
|
+
*
|
|
33298
|
+
* It is sent UNCONDITIONALLY whenever this read returned a version, and the
|
|
33299
|
+
* earlier attempt to scope it to "only when the merge wrote back live
|
|
33300
|
+
* values" was wrong on both counts. Wrong on SAFETY: the merge also reports
|
|
33301
|
+
* nothing-written-back when the live read came back EMPTY, and that update
|
|
33302
|
+
* still ships a wholesale `TableInput` replace — so a commit landing in the
|
|
33303
|
+
* window would have been wiped with no guard at all, i.e. #1461 surviving
|
|
33304
|
+
* its own fix. Wrong on its PREMISE: this read runs milliseconds before the
|
|
33305
|
+
* send on every update, so a pure template push (`cdkd drift --revert`, the
|
|
33306
|
+
* case the scoping was meant to protect) carries a FRESH version too. An
|
|
33307
|
+
* unconditional guard therefore cannot fire spuriously — it fires only when
|
|
33308
|
+
* somebody else genuinely wrote in between, which is exactly when a revert
|
|
33309
|
+
* should stop and be re-run against current values rather than clobber a
|
|
33310
|
+
* change it never saw.
|
|
33311
|
+
*
|
|
33312
|
+
* The precondition's real-AWS semantics are pinned by the `data-analytics`
|
|
33313
|
+
* integ, which advances a table's version out of band and asserts cdkd's
|
|
33314
|
+
* update is REFUSED — without that, "AWS silently ignores a stale VersionId"
|
|
33315
|
+
* would make this guard a placebo.
|
|
33316
|
+
*/
|
|
33317
|
+
async readLiveTableState(logicalId, resourceType, physicalId, databaseName, tableName, catalogId) {
|
|
33318
|
+
try {
|
|
33319
|
+
const resp = await this.getClient().send(new GetTableCommand({
|
|
33320
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33321
|
+
DatabaseName: databaseName,
|
|
33322
|
+
Name: tableName
|
|
33323
|
+
}));
|
|
33324
|
+
return {
|
|
33325
|
+
parameters: resp.Table?.Parameters,
|
|
33326
|
+
versionId: resp.Table?.VersionId
|
|
33327
|
+
};
|
|
33328
|
+
} catch (error) {
|
|
33329
|
+
if (error instanceof EntityNotFoundException) return {
|
|
33330
|
+
parameters: void 0,
|
|
33331
|
+
versionId: void 0
|
|
33332
|
+
};
|
|
33333
|
+
throw new ProvisioningError(preUpdateReadFailureMessage("Table", "glue:GetTable", logicalId, error), resourceType, logicalId, physicalId, error instanceof Error ? error : void 0);
|
|
33334
|
+
}
|
|
33335
|
+
}
|
|
33336
|
+
/**
|
|
33337
|
+
* `Database.Parameters` as AWS currently holds them, for
|
|
33338
|
+
* {@link preserveAwsManagedParameters}. Same not-found / fail-closed
|
|
33339
|
+
* contract as {@link readLiveTableState}.
|
|
33340
|
+
*
|
|
33341
|
+
* There is NO `VersionId` analogue here: `UpdateDatabaseRequest` has no such
|
|
33342
|
+
* member (verified against `@aws-sdk/client-glue`), so the database merge
|
|
33343
|
+
* carries the TOCTOU exposure the table merge closes. It is far narrower in
|
|
33344
|
+
* practice — nothing commits to a Glue DATABASE out of band the way an
|
|
33345
|
+
* Iceberg engine commits to a table — but it is real, and is written up in
|
|
33346
|
+
* docs/supported-resources.md rather than left implicit.
|
|
33347
|
+
*/
|
|
33348
|
+
async readLiveDatabaseParameters(logicalId, resourceType, physicalId, catalogId) {
|
|
33349
|
+
try {
|
|
33350
|
+
return (await this.getClient().send(new GetDatabaseCommand({
|
|
33351
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33352
|
+
Name: physicalId
|
|
33353
|
+
}))).Database?.Parameters;
|
|
33354
|
+
} catch (error) {
|
|
33355
|
+
if (error instanceof EntityNotFoundException) return void 0;
|
|
33356
|
+
throw new ProvisioningError(preUpdateReadFailureMessage("Database", "glue:GetDatabase", logicalId, error), resourceType, logicalId, physicalId, error instanceof Error ? error : void 0);
|
|
33357
|
+
}
|
|
33358
|
+
}
|
|
33359
|
+
/**
|
|
33203
33360
|
* Build DatabaseInput for Glue API from CFn template properties.
|
|
33204
33361
|
*
|
|
33205
33362
|
* Used by both `createDatabase` and `updateDatabase` so the same
|
|
@@ -33213,7 +33370,7 @@ var GlueProvider = class {
|
|
|
33213
33370
|
const result = { Name: databaseInput["Name"] ?? fallbackName };
|
|
33214
33371
|
if (databaseInput["Description"] !== void 0) result.Description = databaseInput["Description"];
|
|
33215
33372
|
if (databaseInput["LocationUri"] !== void 0) result.LocationUri = databaseInput["LocationUri"];
|
|
33216
|
-
if (databaseInput["Parameters"] !== void 0) result.Parameters = databaseInput["Parameters"];
|
|
33373
|
+
if (databaseInput["Parameters"] !== void 0) result.Parameters = stringifyParameterValues(databaseInput["Parameters"]);
|
|
33217
33374
|
return result;
|
|
33218
33375
|
}
|
|
33219
33376
|
/**
|
|
@@ -33223,12 +33380,7 @@ var GlueProvider = class {
|
|
|
33223
33380
|
const result = { Name: tableInput["Name"] ?? fallbackName };
|
|
33224
33381
|
if (tableInput["Description"] !== void 0) result.Description = tableInput["Description"];
|
|
33225
33382
|
if (tableInput["TableType"] !== void 0) result.TableType = tableInput["TableType"];
|
|
33226
|
-
if (tableInput["Parameters"] !== void 0)
|
|
33227
|
-
const rawParams = tableInput["Parameters"];
|
|
33228
|
-
const params = {};
|
|
33229
|
-
for (const [k, v] of Object.entries(rawParams)) params[k] = String(v);
|
|
33230
|
-
result.Parameters = params;
|
|
33231
|
-
}
|
|
33383
|
+
if (tableInput["Parameters"] !== void 0) result.Parameters = stringifyParameterValues(tableInput["Parameters"]);
|
|
33232
33384
|
if (tableInput["Owner"] !== void 0) result.Owner = tableInput["Owner"];
|
|
33233
33385
|
if (tableInput["Retention"] !== void 0) result.Retention = tableInput["Retention"];
|
|
33234
33386
|
if (tableInput["ViewOriginalText"] !== void 0) result.ViewOriginalText = tableInput["ViewOriginalText"];
|
|
@@ -33300,10 +33452,11 @@ var GlueProvider = class {
|
|
|
33300
33452
|
* the provider's `create()` only handles Database/Table; CC API picks
|
|
33301
33453
|
* up drift detection for the rest.
|
|
33302
33454
|
*/
|
|
33303
|
-
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
33455
|
+
async readCurrentState(physicalId, _logicalId, resourceType, properties) {
|
|
33456
|
+
const catalogId = properties?.["CatalogId"];
|
|
33304
33457
|
switch (resourceType) {
|
|
33305
|
-
case "AWS::Glue::Database": return this.readDatabase(physicalId);
|
|
33306
|
-
case "AWS::Glue::Table": return this.readTable(physicalId);
|
|
33458
|
+
case "AWS::Glue::Database": return this.readDatabase(physicalId, catalogId);
|
|
33459
|
+
case "AWS::Glue::Table": return this.readTable(physicalId, catalogId);
|
|
33307
33460
|
default: return;
|
|
33308
33461
|
}
|
|
33309
33462
|
}
|
|
@@ -33321,10 +33474,13 @@ var GlueProvider = class {
|
|
|
33321
33474
|
if (resourceType === "AWS::Glue::Table") return ["OpenTableFormatInput"];
|
|
33322
33475
|
return [];
|
|
33323
33476
|
}
|
|
33324
|
-
async readDatabase(physicalId) {
|
|
33477
|
+
async readDatabase(physicalId, catalogId) {
|
|
33325
33478
|
let db;
|
|
33326
33479
|
try {
|
|
33327
|
-
db = (await this.getClient().send(new GetDatabaseCommand({
|
|
33480
|
+
db = (await this.getClient().send(new GetDatabaseCommand({
|
|
33481
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33482
|
+
Name: physicalId
|
|
33483
|
+
}))).Database;
|
|
33328
33484
|
} catch (err) {
|
|
33329
33485
|
if (err instanceof EntityNotFoundException) return void 0;
|
|
33330
33486
|
throw err;
|
|
@@ -33339,12 +33495,13 @@ var GlueProvider = class {
|
|
|
33339
33495
|
if (db.Name !== void 0) result["DatabaseName"] = db.Name;
|
|
33340
33496
|
return result;
|
|
33341
33497
|
}
|
|
33342
|
-
async readTable(physicalId) {
|
|
33498
|
+
async readTable(physicalId, catalogId) {
|
|
33343
33499
|
const [databaseName, tableName] = physicalId.split("|");
|
|
33344
33500
|
if (!databaseName || !tableName) return void 0;
|
|
33345
33501
|
let table;
|
|
33346
33502
|
try {
|
|
33347
33503
|
table = (await this.getClient().send(new GetTableCommand({
|
|
33504
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33348
33505
|
DatabaseName: databaseName,
|
|
33349
33506
|
Name: tableName
|
|
33350
33507
|
}))).Table;
|
|
@@ -34161,6 +34318,35 @@ function buildJobCommonFields(p) {
|
|
|
34161
34318
|
return r;
|
|
34162
34319
|
}
|
|
34163
34320
|
/**
|
|
34321
|
+
* CFn `Parameters` map -> the SDK's `Record<string, string>`. CDK may deliver
|
|
34322
|
+
* booleans / numbers; the SDK member is string-valued.
|
|
34323
|
+
*/
|
|
34324
|
+
function stringifyParameterValues(raw) {
|
|
34325
|
+
const params = {};
|
|
34326
|
+
for (const [k, v] of Object.entries(raw ?? {})) params[k] = String(v);
|
|
34327
|
+
return params;
|
|
34328
|
+
}
|
|
34329
|
+
/**
|
|
34330
|
+
* Key set of a CFn-side `Parameters` map, for
|
|
34331
|
+
* {@link GlueProvider.preserveAwsManagedParameters}.
|
|
34332
|
+
*
|
|
34333
|
+
* A non-object (absent, or an unresolved intrinsic) contributes NO keys — so
|
|
34334
|
+
* a template that declares no `Parameters` at all can never be mistaken for
|
|
34335
|
+
* one that removed a key, and every live key stays preserved.
|
|
34336
|
+
*/
|
|
34337
|
+
function parameterKeySet(value) {
|
|
34338
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return /* @__PURE__ */ new Set();
|
|
34339
|
+
return new Set(Object.keys(value));
|
|
34340
|
+
}
|
|
34341
|
+
/**
|
|
34342
|
+
* Message for a failed pre-update `Get*` read (issue #1461). Names the IAM
|
|
34343
|
+
* action so a permission gap is one line away from fixed, and says what the
|
|
34344
|
+
* read is FOR so the failure does not read as gratuitous.
|
|
34345
|
+
*/
|
|
34346
|
+
function preUpdateReadFailureMessage(kind, iamAction, logicalId, error) {
|
|
34347
|
+
return `Failed to read the current Glue ${kind} ${logicalId} before update: ${error instanceof Error ? error.message : String(error)}. cdkd reads the live ${kind.toLowerCase()} so AWS-managed Parameters (Apache Iceberg's table_type / metadata_location, a crawler's classification, Lake Formation markers) survive an update that Glue applies as a full replace. Grant ${iamAction} to the deploy identity — proceeding without the read would silently erase them.`;
|
|
34348
|
+
}
|
|
34349
|
+
/**
|
|
34164
34350
|
* Coerce a CFn-delivered numeric property (often a string like `"10"`) to a
|
|
34165
34351
|
* JS number at the SDK wire boundary. Non-finite / unparseable inputs are
|
|
34166
34352
|
* returned unchanged so AWS surfaces a clear validation error rather than
|
|
@@ -65598,7 +65784,7 @@ function createMigrateCommand() {
|
|
|
65598
65784
|
*/
|
|
65599
65785
|
function buildProgram() {
|
|
65600
65786
|
const program = new Command();
|
|
65601
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.
|
|
65787
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.23");
|
|
65602
65788
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
65603
65789
|
const { profile } = actionCommand.optsWithGlobals();
|
|
65604
65790
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|