@go-to-k/cdkd 0.283.5 → 0.283.7
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-B9eSuRPc.js → asg-provider-o7QsopaI.js} +2 -2
- package/dist/{asg-provider-B9eSuRPc.js.map → asg-provider-o7QsopaI.js.map} +1 -1
- package/dist/cli.js +190 -11
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-BcwNPlSk.js → deploy-engine-CKpBSlde.js} +41 -7
- package/dist/deploy-engine-CKpBSlde.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-BcwNPlSk.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as configStringRefusal, $t as resolveSkipPrefix, A as green, At as rewriteTemplateAssetReferences, B as slowCcOperationTimeoutMs, Bt as formatDockerLoginError, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as CdkdError, Ct as shouldRetainResource, D as bold, Dn as LocalInvokeBuildError$1, Dt as buildAssetRedirectMap, E as formatResourceLine, En as DeployCancelledError, Et as WorkGraph, F as clearOnUpdateRemoval, Fn as ResourceTimeoutError, Ft as parseBootstrapMarker, G as getAccountInfo, Gt as getDockerImageBySourceHash, H as isTerminationProtectionPropagationError, Ht as runDockerForeground, I as ProviderRegistry, In as ResourceUpdateNotSupportedError, It as validateAssetBucketName, J as normalizeAwsTagsToCfn, Jt as getDefaultStateBucketName, K as refStateLookupFromResource, Kt as Synthesizer, L as findActionableSilentDrops, Ln as StackHasActiveImportsError, Lt as validateContainerRepoName, M as yellow, Mn as NestedStackChildDirectDestroyError, Mt as BOOTSTRAP_MARKER_PREFIX, N as IAMRoleProvider, Nn as PartialFailureError, Nt as ensureAssetStorage, O as cyan, On as LocalMigrateError, Ot as createAssetRedirectResolver, P as collectInlinePolicyNamesManagedBySiblings, Pn as ProvisioningError, Pt as getBootstrapMarkerKey, Q as configBooleanRefusal, Qt as resolveCaptureObservedState, R as findSilentDropProperties, Rn as StackTerminationProtectionError, Rt as buildDenyExternalAccessPolicy, S as extractDeploymentEventError, St as rebuildClientForBucketRegion, T as renderStatefulReason, Tt as stringifyValue, U as IntrinsicFunctionResolver, Un as normalizeAwsError, Ut as runDockerStreaming, V as disableInstanceApiTermination, Vt as getDockerCmd, W as cfnRefValueFromPhysicalId, Wn as withErrorHandling, Wt as AssetManifestLoader, X as assertRegionMatch, Xt as resolveApp, Y as resolveExplicitPhysicalId, Yt as getLegacyStateBucketName, Z as coerceCfnBoolean, Zt as resolveAutoAssetStorage, _ as createPreDeleteFinalSnapshot, _n as resolveBucketRegion, _t as markNonRetryable, a as DeploymentEventsStore, an as CFN_TEMPLATE_BODY_LIMIT, at as s3BucketArn, b as unsupportedFinalSnapshotError, bn as resetAwsClients, bt as LockManager, c as replayFailedOperations, cn as findLargeInlineResources, ct as s3BucketRegionalDomainName, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PARTITION_TABLE, dt as DiffCalculator, en as resolveStateBucketWithDefault, et as readConfigString, f as computeImplicitDeleteEdges, fn as canonicalizeRegion, ft as describeTypeWithThrottleRetry, g as ccRoutedFinalSnapshotError, gt as isThrottlingError, h as buildFinalSnapshotIdentifier, hn as processStackMessages, ht as isRetryableTransientError, i as DeploymentEventsReader, in as warnDeprecatedNoPrefixCliFlag, it as requireConfigString, j as red, jn as MissingCdkCliError, jt as AssetModeResolver, k as gray, kn as LocalStartServiceError, kt as loadPublishableAssetManifest, l as replayRollback, ln as uploadCfnTemplate, lt as s3BucketWebsiteUrl, m as PRE_DELETE_SNAPSHOT_TYPES, mn as AssemblyReader, mt as isMarkedNonRetryable, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveUseCdkBootstrapAssets, nt as requireConfigArray, o as planFailedOps, on as CFN_TEMPLATE_URL_LIMIT, ot as s3BucketDomainName, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as derivePartitionAndUrlSuffix, pt as withRetry, q as WAFv2WebACLProvider, qt as synthesisStatusMessage, r as DeployEngine, rn as stateBucketExistenceConfirmed, rt as requireConfigObject, s as planRollback, sn as MIGRATE_TMP_PREFIX, st as s3BucketDualStackDomainName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resolveStateBucketWithDefaultAndSource, tt as replayWarn, u as withResourceDeadline, un as expectedOwnerParam, ut as applyRoleArnIfSet, v as isFinalSnapshotError, vn as AwsClients, vt as DagBuilder, w as isStatefulRecreateTargetSync, wt as AssetPublisher, x as makeCanonicalizePropertiesFn, xn as setAwsClients, xt as S3StateBackend, y as refusesFinalSnapshot, yn as getAwsClients, yt as TemplateParser, z as CloudControlProvider, zt as buildDockerImage } from "./deploy-engine-
|
|
2
|
+
import { $ as configStringRefusal, $t as resolveSkipPrefix, A as green, At as rewriteTemplateAssetReferences, B as slowCcOperationTimeoutMs, Bt as formatDockerLoginError, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as CdkdError, Ct as shouldRetainResource, D as bold, Dn as LocalInvokeBuildError$1, Dt as buildAssetRedirectMap, E as formatResourceLine, En as DeployCancelledError, Et as WorkGraph, F as clearOnUpdateRemoval, Fn as ResourceTimeoutError, Ft as parseBootstrapMarker, G as getAccountInfo, Gt as getDockerImageBySourceHash, H as isTerminationProtectionPropagationError, Ht as runDockerForeground, I as ProviderRegistry, In as ResourceUpdateNotSupportedError, It as validateAssetBucketName, J as normalizeAwsTagsToCfn, Jt as getDefaultStateBucketName, K as refStateLookupFromResource, Kt as Synthesizer, L as findActionableSilentDrops, Ln as StackHasActiveImportsError, Lt as validateContainerRepoName, M as yellow, Mn as NestedStackChildDirectDestroyError, Mt as BOOTSTRAP_MARKER_PREFIX, N as IAMRoleProvider, Nn as PartialFailureError, Nt as ensureAssetStorage, O as cyan, On as LocalMigrateError, Ot as createAssetRedirectResolver, P as collectInlinePolicyNamesManagedBySiblings, Pn as ProvisioningError, Pt as getBootstrapMarkerKey, Q as configBooleanRefusal, Qt as resolveCaptureObservedState, R as findSilentDropProperties, Rn as StackTerminationProtectionError, Rt as buildDenyExternalAccessPolicy, S as extractDeploymentEventError, St as rebuildClientForBucketRegion, T as renderStatefulReason, Tt as stringifyValue, U as IntrinsicFunctionResolver, Un as normalizeAwsError, Ut as runDockerStreaming, V as disableInstanceApiTermination, Vt as getDockerCmd, W as cfnRefValueFromPhysicalId, Wn as withErrorHandling, Wt as AssetManifestLoader, X as assertRegionMatch, Xt as resolveApp, Y as resolveExplicitPhysicalId, Yt as getLegacyStateBucketName, Z as coerceCfnBoolean, Zt as resolveAutoAssetStorage, _ as createPreDeleteFinalSnapshot, _n as resolveBucketRegion, _t as markNonRetryable, a as DeploymentEventsStore, an as CFN_TEMPLATE_BODY_LIMIT, at as s3BucketArn, b as unsupportedFinalSnapshotError, bn as resetAwsClients, bt as LockManager, c as replayFailedOperations, cn as findLargeInlineResources, ct as s3BucketRegionalDomainName, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PARTITION_TABLE, dt as DiffCalculator, en as resolveStateBucketWithDefault, et as readConfigString, f as computeImplicitDeleteEdges, fn as canonicalizeRegion, ft as describeTypeWithThrottleRetry, g as ccRoutedFinalSnapshotError, gt as isThrottlingError, h as buildFinalSnapshotIdentifier, hn as processStackMessages, ht as isRetryableTransientError, i as DeploymentEventsReader, in as warnDeprecatedNoPrefixCliFlag, it as requireConfigString, j as red, jn as MissingCdkCliError, jt as AssetModeResolver, k as gray, kn as LocalStartServiceError, kt as loadPublishableAssetManifest, l as replayRollback, ln as uploadCfnTemplate, lt as s3BucketWebsiteUrl, m as PRE_DELETE_SNAPSHOT_TYPES, mn as AssemblyReader, mt as isMarkedNonRetryable, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveUseCdkBootstrapAssets, nt as requireConfigArray, o as planFailedOps, on as CFN_TEMPLATE_URL_LIMIT, ot as s3BucketDomainName, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as derivePartitionAndUrlSuffix, pt as withRetry, q as WAFv2WebACLProvider, qt as synthesisStatusMessage, r as DeployEngine, rn as stateBucketExistenceConfirmed, rt as requireConfigObject, s as planRollback, sn as MIGRATE_TMP_PREFIX, st as s3BucketDualStackDomainName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resolveStateBucketWithDefaultAndSource, tt as replayWarn, u as withResourceDeadline, un as expectedOwnerParam, ut as applyRoleArnIfSet, v as isFinalSnapshotError, vn as AwsClients, vt as DagBuilder, w as isStatefulRecreateTargetSync, wt as AssetPublisher, x as makeCanonicalizePropertiesFn, xn as setAwsClients, xt as S3StateBackend, y as refusesFinalSnapshot, yn as getAwsClients, yt as TemplateParser, z as CloudControlProvider, zt as buildDockerImage } from "./deploy-engine-CKpBSlde.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-o7QsopaI.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";
|
|
@@ -40935,7 +40935,7 @@ var GlueProvider = class {
|
|
|
40935
40935
|
}
|
|
40936
40936
|
async create(logicalId, resourceType, properties, context) {
|
|
40937
40937
|
switch (resourceType) {
|
|
40938
|
-
case "AWS::Glue::Database": return this.createDatabase(logicalId, resourceType, properties);
|
|
40938
|
+
case "AWS::Glue::Database": return this.createDatabase(logicalId, resourceType, properties, context);
|
|
40939
40939
|
case "AWS::Glue::Table": return this.createTable(logicalId, resourceType, properties, context);
|
|
40940
40940
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
|
|
40941
40941
|
}
|
|
@@ -40954,7 +40954,7 @@ var GlueProvider = class {
|
|
|
40954
40954
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
40955
40955
|
}
|
|
40956
40956
|
}
|
|
40957
|
-
async createDatabase(logicalId, resourceType, properties) {
|
|
40957
|
+
async createDatabase(logicalId, resourceType, properties, context) {
|
|
40958
40958
|
this.logger.debug(`Creating Glue Database ${logicalId}`);
|
|
40959
40959
|
const databaseInput = properties["DatabaseInput"];
|
|
40960
40960
|
if (!databaseInput) throw new ProvisioningError(`DatabaseInput is required for Glue Database ${logicalId}`, resourceType, logicalId);
|
|
@@ -40964,7 +40964,7 @@ var GlueProvider = class {
|
|
|
40964
40964
|
try {
|
|
40965
40965
|
await this.getClient().send(new CreateDatabaseCommand({
|
|
40966
40966
|
CatalogId: catalogId,
|
|
40967
|
-
DatabaseInput: this.buildDatabaseInput(databaseInput, databaseName)
|
|
40967
|
+
DatabaseInput: this.buildDatabaseInput(databaseInput, databaseName, { ...replayWarn(this.logger, context) })
|
|
40968
40968
|
}));
|
|
40969
40969
|
this.logger.debug(`Successfully created Glue Database ${logicalId}: ${databaseName}`);
|
|
40970
40970
|
return {
|
|
@@ -40982,9 +40982,13 @@ var GlueProvider = class {
|
|
|
40982
40982
|
if (!databaseInput) throw new ProvisioningError(`DatabaseInput is required for Glue Database update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
40983
40983
|
const catalogId = properties["CatalogId"];
|
|
40984
40984
|
const liveParameters = await this.readLiveDatabaseParameters(logicalId, resourceType, physicalId, catalogId);
|
|
40985
|
+
const previousDatabaseInput = asRecord(previousProperties?.["DatabaseInput"]);
|
|
40985
40986
|
try {
|
|
40986
|
-
const builtDatabaseInput = this.buildDatabaseInput(databaseInput, physicalId
|
|
40987
|
-
|
|
40987
|
+
const builtDatabaseInput = this.buildDatabaseInput(databaseInput, physicalId, {
|
|
40988
|
+
onUnusable: (message) => this.logger.warn(message),
|
|
40989
|
+
previousDatabaseInput
|
|
40990
|
+
});
|
|
40991
|
+
this.preserveAwsManagedParameters(builtDatabaseInput, databaseInput["Parameters"], previousDatabaseInput?.["Parameters"], liveParameters);
|
|
40988
40992
|
await this.getClient().send(new UpdateDatabaseCommand({
|
|
40989
40993
|
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
40990
40994
|
Name: physicalId,
|
|
@@ -41358,15 +41362,137 @@ var GlueProvider = class {
|
|
|
41358
41362
|
* so empty-string Description, empty Parameters map, etc. reach AWS
|
|
41359
41363
|
* intact — `cdkd drift --revert` relies on this to clear console-side
|
|
41360
41364
|
* additions.
|
|
41361
|
-
|
|
41362
|
-
|
|
41365
|
+
*
|
|
41366
|
+
* `options` carries the shape-guard policy for the three nested blocks added
|
|
41367
|
+
* by issue #1807, and the two call sites answer differently because their
|
|
41368
|
+
* desired bag has a different provenance (`.claude/rules/providers.md`):
|
|
41369
|
+
*
|
|
41370
|
+
* - CREATE passes NO `onUnusable`, so a malformed block is REFUSED before
|
|
41371
|
+
* the AWS call — the value is template-borne, and the alternative is
|
|
41372
|
+
* sending an empty `{}` block AWS would reject with a far less
|
|
41373
|
+
* actionable message. Under `CreateContext.replayingState` the refusal
|
|
41374
|
+
* downgrades through the shared `replayWarn`, since a reverse-replacement
|
|
41375
|
+
* re-create reads a STATE record the user cannot edit from the template.
|
|
41376
|
+
* - UPDATE passes a warn callback UNCONDITIONALLY (the `updateRoute`
|
|
41377
|
+
* precedent — `update()` has no context, so it cannot tell a template
|
|
41378
|
+
* push from the state-borne bag `drift --revert` and the rollback revert
|
|
41379
|
+
* arm hand it), and then RETAINS the PREVIOUS side's block, which is why
|
|
41380
|
+
* `previousDatabaseInput` is threaded in. Omitting instead would ERASE a
|
|
41381
|
+
* live resource link, because `UpdateDatabase` replaces `DatabaseInput`
|
|
41382
|
+
* wholesale — the #1612 "UPDATE retains the previous value" row, reached
|
|
41383
|
+
* here through a whole-blob API rather than a per-item one. When the
|
|
41384
|
+
* previous side is unusable too the key is DROPPED: there is no value
|
|
41385
|
+
* cdkd can vouch for either way (#1653 review).
|
|
41386
|
+
*/
|
|
41387
|
+
buildDatabaseInput(databaseInput, fallbackName, options) {
|
|
41388
|
+
const guardOptions = options?.onUnusable ? { onUnusable: options.onUnusable } : void 0;
|
|
41389
|
+
const previous = options?.previousDatabaseInput;
|
|
41390
|
+
/**
|
|
41391
|
+
* The record a nested block is BUILT FROM: the desired side when it names
|
|
41392
|
+
* at least one sendable member, else the previous side when IT does, else
|
|
41393
|
+
* nothing.
|
|
41394
|
+
*
|
|
41395
|
+
* The emptiness test is what makes the ladder complete, and getting it
|
|
41396
|
+
* wrong is how the first cut of this guard still erased a live resource
|
|
41397
|
+
* link: a bare `{}` and an unresolved `{Ref: ...}` are plain OBJECTS, so
|
|
41398
|
+
* the shape guard accepts them and a `?? previous` fallback never fires —
|
|
41399
|
+
* the block then built empty and `UpdateDatabase`, which replaces
|
|
41400
|
+
* `DatabaseInput` wholesale, dropped a link the template still declared.
|
|
41401
|
+
*
|
|
41402
|
+
* A member counts as sendable only when it is a STRING or a NUMBER: the
|
|
41403
|
+
* leaf casts below are unchecked, so an intrinsic-valued `DatabaseName`
|
|
41404
|
+
* would otherwise put an OBJECT on the wire — the same defect one level in.
|
|
41405
|
+
*/
|
|
41406
|
+
const pickBlockSource = (desiredRaw, previousRaw, path, block, members) => {
|
|
41407
|
+
const namesSendable = (bag) => {
|
|
41408
|
+
if (bag === void 0) return false;
|
|
41409
|
+
const present = members.filter((m) => bag[m] !== void 0);
|
|
41410
|
+
return present.length > 0 && present.every((m) => isSendableLeaf(bag[m]));
|
|
41411
|
+
};
|
|
41412
|
+
const desired = guardOptions ? requireConfigObject(desiredRaw, path, guardOptions) : requireConfigObject(desiredRaw, path);
|
|
41413
|
+
if (namesSendable(desired)) return desired;
|
|
41414
|
+
if (desired !== void 0) {
|
|
41415
|
+
const message = emptyBlockMessage(block);
|
|
41416
|
+
if (options?.onUnusable) options.onUnusable(message);
|
|
41417
|
+
else throw new Error(message);
|
|
41418
|
+
}
|
|
41419
|
+
const retained = asRecord(previousRaw);
|
|
41420
|
+
return namesSendable(retained) ? retained : void 0;
|
|
41421
|
+
};
|
|
41363
41422
|
const result = { Name: databaseInput["Name"] ?? fallbackName };
|
|
41364
41423
|
if (databaseInput["Description"] !== void 0) result.Description = databaseInput["Description"];
|
|
41365
41424
|
if (databaseInput["LocationUri"] !== void 0) result.LocationUri = databaseInput["LocationUri"];
|
|
41366
41425
|
if (databaseInput["Parameters"] !== void 0) result.Parameters = stringifyParameterValues(databaseInput["Parameters"]);
|
|
41426
|
+
if (databaseInput["TargetDatabase"] !== void 0) {
|
|
41427
|
+
const target = pickBlockSource(databaseInput["TargetDatabase"], previous?.["TargetDatabase"], "AWS::Glue::Database DatabaseInput.TargetDatabase", "TargetDatabase", TARGET_DATABASE_MEMBERS);
|
|
41428
|
+
if (target !== void 0) {
|
|
41429
|
+
const targetDatabase = {};
|
|
41430
|
+
if (isSendableLeaf(target["CatalogId"])) targetDatabase.CatalogId = String(target["CatalogId"]);
|
|
41431
|
+
if (isSendableLeaf(target["DatabaseName"])) targetDatabase.DatabaseName = String(target["DatabaseName"]);
|
|
41432
|
+
if (isSendableLeaf(target["Region"])) targetDatabase.Region = String(target["Region"]);
|
|
41433
|
+
result.TargetDatabase = targetDatabase;
|
|
41434
|
+
}
|
|
41435
|
+
}
|
|
41436
|
+
if (databaseInput["FederatedDatabase"] !== void 0) {
|
|
41437
|
+
const federated = pickBlockSource(databaseInput["FederatedDatabase"], previous?.["FederatedDatabase"], "AWS::Glue::Database DatabaseInput.FederatedDatabase", "FederatedDatabase", FEDERATED_DATABASE_MEMBERS);
|
|
41438
|
+
if (federated !== void 0) {
|
|
41439
|
+
const federatedDatabase = {};
|
|
41440
|
+
if (isSendableLeaf(federated["ConnectionName"])) federatedDatabase.ConnectionName = String(federated["ConnectionName"]);
|
|
41441
|
+
if (isSendableLeaf(federated["Identifier"])) federatedDatabase.Identifier = String(federated["Identifier"]);
|
|
41442
|
+
result.FederatedDatabase = federatedDatabase;
|
|
41443
|
+
}
|
|
41444
|
+
}
|
|
41445
|
+
if (databaseInput["CreateTableDefaultPermissions"] !== void 0) {
|
|
41446
|
+
const permissions = this.usableDefaultPermissions(databaseInput["CreateTableDefaultPermissions"], guardOptions) ?? this.usableDefaultPermissions(previous?.["CreateTableDefaultPermissions"], { onUnusable: () => void 0 });
|
|
41447
|
+
if (permissions !== void 0) result.CreateTableDefaultPermissions = permissions.map((entry) => {
|
|
41448
|
+
const permission = {};
|
|
41449
|
+
if (entry["Permissions"] !== void 0) permission.Permissions = entry["Permissions"];
|
|
41450
|
+
const declaredPrincipal = asRecord(entry["Principal"]);
|
|
41451
|
+
if (declaredPrincipal !== void 0) {
|
|
41452
|
+
const principal = {};
|
|
41453
|
+
if (isSendableLeaf(declaredPrincipal["DataLakePrincipalIdentifier"])) principal.DataLakePrincipalIdentifier = String(declaredPrincipal["DataLakePrincipalIdentifier"]);
|
|
41454
|
+
permission.Principal = principal;
|
|
41455
|
+
}
|
|
41456
|
+
return permission;
|
|
41457
|
+
});
|
|
41458
|
+
}
|
|
41367
41459
|
return result;
|
|
41368
41460
|
}
|
|
41369
41461
|
/**
|
|
41462
|
+
* `DatabaseInput.CreateTableDefaultPermissions` as a USABLE list, or
|
|
41463
|
+
* `undefined` when the declared value is a shape cdkd refuses to narrow.
|
|
41464
|
+
*
|
|
41465
|
+
* The block is validated ALL-OR-NOTHING rather than per entry, which is the
|
|
41466
|
+
* opposite of the S3 per-`Id` appliers and deliberate: this is a Lake
|
|
41467
|
+
* Formation grant list delivered by ONE wholesale `CreateDatabase` /
|
|
41468
|
+
* `UpdateDatabase` call, so dropping the entries cdkd cannot read would
|
|
41469
|
+
* silently NARROW the permissions the template declared — the failure this
|
|
41470
|
+
* guard exists to prevent, one level in from the block itself. A malformed
|
|
41471
|
+
* ENTRY therefore invalidates the block, and the caller then refuses (create)
|
|
41472
|
+
* or retains the previous list (update).
|
|
41473
|
+
*
|
|
41474
|
+
* `Permissions` is checked for ARRAY-ness for the same reason: the SDK member
|
|
41475
|
+
* is `Permission[]`, so a bare string would be forwarded verbatim and the
|
|
41476
|
+
* serializer would drop it, granting nothing while the deploy reports success.
|
|
41477
|
+
*/
|
|
41478
|
+
usableDefaultPermissions(value, guardOptions) {
|
|
41479
|
+
if (value === void 0) return void 0;
|
|
41480
|
+
const path = "AWS::Glue::Database DatabaseInput.CreateTableDefaultPermissions";
|
|
41481
|
+
const entries = guardOptions ? requireConfigArray(value, path, guardOptions) : requireConfigArray(value, path);
|
|
41482
|
+
if (entries === void 0) return void 0;
|
|
41483
|
+
for (const entry of entries) {
|
|
41484
|
+
const principal = asRecord(entry["Principal"]);
|
|
41485
|
+
if (asRecord(entry) !== void 0 && (entry["Permissions"] !== void 0 || entry["Principal"] !== void 0) && (entry["Permissions"] === void 0 || Array.isArray(entry["Permissions"])) && (entry["Principal"] === void 0 || principal !== void 0 && isSendableLeaf(principal["DataLakePrincipalIdentifier"]))) continue;
|
|
41486
|
+
const detail = `${path} carries an entry cdkd cannot read (each entry must be an object naming Permissions as a list and/or Principal as an object whose DataLakePrincipalIdentifier is a string or a number)`;
|
|
41487
|
+
if (guardOptions?.onUnusable) {
|
|
41488
|
+
guardOptions.onUnusable(`${detail}. Leaving the whole block unapplied rather than sending a NARROWED grant list. On an UPDATE that is a RESET: UpdateDatabase replaces DatabaseInput wholesale, so unless a usable previous list is retained the database falls back to the account default (IAM_ALLOWED_PRINCIPALS / ALL) — fix the template value to restore the declared grants`);
|
|
41489
|
+
return;
|
|
41490
|
+
}
|
|
41491
|
+
throw new Error(detail);
|
|
41492
|
+
}
|
|
41493
|
+
return entries;
|
|
41494
|
+
}
|
|
41495
|
+
/**
|
|
41370
41496
|
* Build TableInput for Glue API from CFn template properties
|
|
41371
41497
|
*/
|
|
41372
41498
|
buildTableInput(tableInput, fallbackName) {
|
|
@@ -41476,9 +41602,30 @@ var GlueProvider = class {
|
|
|
41476
41602
|
* readback for it (and fabricating a placeholder would itself fire false
|
|
41477
41603
|
* drift). Declaring it here keeps the drift comparator from false-positiving
|
|
41478
41604
|
* on a state-recorded `OpenTableFormatInput` that the readback never surfaces.
|
|
41605
|
+
*
|
|
41606
|
+
* `AWS::Glue::Database` declares `DatabaseInput.CreateTableDefaultPermissions`
|
|
41607
|
+
* PER RESOURCE (the issue #1602 seam), and only for a database whose template
|
|
41608
|
+
* does NOT declare the block. AWS materializes a Lake Formation DEFAULT there
|
|
41609
|
+
* — `[{IAM_ALLOWED_PRINCIPALS, [ALL]}]` on a catalog that has not been
|
|
41610
|
+
* onboarded to Lake Formation (measured us-east-1, 2026-08-13) — so once
|
|
41611
|
+
* issue #1807 taught `readDatabase` to surface the block, comparing it would
|
|
41612
|
+
* report drift on EVERY existing database: the baseline is an
|
|
41613
|
+
* `observedProperties` capture written by a binary that did not read the key,
|
|
41614
|
+
* `drift.ts` walks the key UNION on that baseline (`unionWalkObjects`), and
|
|
41615
|
+
* `deploy-engine.ts` does not refresh a record that already has one — so the
|
|
41616
|
+
* phantom would persist until an unrelated UPDATE or a `drift --accept`.
|
|
41617
|
+
* This is the ELBv2 `Targets` shape one type over: a value a SIBLING owns is
|
|
41618
|
+
* ignored while the template declares none, and an explicit declaration —
|
|
41619
|
+
* including an empty list — IS a declaration and stays compared.
|
|
41620
|
+
*
|
|
41621
|
+
* `TargetDatabase` / `FederatedDatabase` need no such scoping: AWS reports
|
|
41622
|
+
* them only when they were actually set, so an appearance is real drift.
|
|
41479
41623
|
*/
|
|
41480
|
-
getDriftUnknownPaths(resourceType) {
|
|
41624
|
+
getDriftUnknownPaths(resourceType, properties) {
|
|
41481
41625
|
if (resourceType === "AWS::Glue::Table") return ["OpenTableFormatInput"];
|
|
41626
|
+
if (resourceType === "AWS::Glue::Database") {
|
|
41627
|
+
if (asRecord(properties?.["DatabaseInput"])?.["CreateTableDefaultPermissions"] === void 0) return ["DatabaseInput.CreateTableDefaultPermissions"];
|
|
41628
|
+
}
|
|
41482
41629
|
return [];
|
|
41483
41630
|
}
|
|
41484
41631
|
async readDatabase(physicalId, catalogId) {
|
|
@@ -41498,6 +41645,9 @@ var GlueProvider = class {
|
|
|
41498
41645
|
dbInput["Description"] = db.Description ?? "";
|
|
41499
41646
|
if (db.LocationUri !== void 0) dbInput["LocationUri"] = db.LocationUri;
|
|
41500
41647
|
dbInput["Parameters"] = db.Parameters ?? {};
|
|
41648
|
+
if (db.TargetDatabase !== void 0) dbInput["TargetDatabase"] = { ...db.TargetDatabase };
|
|
41649
|
+
if (db.FederatedDatabase !== void 0) dbInput["FederatedDatabase"] = { ...db.FederatedDatabase };
|
|
41650
|
+
if (db.CreateTableDefaultPermissions !== void 0) dbInput["CreateTableDefaultPermissions"] = db.CreateTableDefaultPermissions.map((entry) => ({ ...entry }));
|
|
41501
41651
|
const result = { DatabaseInput: dbInput };
|
|
41502
41652
|
if (db.Name !== void 0) result["DatabaseName"] = db.Name;
|
|
41503
41653
|
return result;
|
|
@@ -42380,6 +42530,35 @@ function parameterKeySet(value) {
|
|
|
42380
42530
|
* its `Fn::*`/`Ref` key — harmless here, since providers only ever see
|
|
42381
42531
|
* resolved values.)
|
|
42382
42532
|
*/
|
|
42533
|
+
/**
|
|
42534
|
+
* The CFn members of the two `DatabaseInput` object blocks, as the SENDABLE-ness
|
|
42535
|
+
* test sees them. They must stay in step with the per-member writes in
|
|
42536
|
+
* `buildDatabaseInput` — a name here that the builder does not write would let
|
|
42537
|
+
* an EMPTY block onto the wire, and one the builder writes but this list omits
|
|
42538
|
+
* would refuse a valid template that names only it. The unit suite fences both
|
|
42539
|
+
* directions by asserting each member ALONE reaches AWS, which fails on a
|
|
42540
|
+
* dropped entry (the member stops being sendable) and on an added one (the
|
|
42541
|
+
* block builds empty).
|
|
42542
|
+
*/
|
|
42543
|
+
const TARGET_DATABASE_MEMBERS = [
|
|
42544
|
+
"CatalogId",
|
|
42545
|
+
"DatabaseName",
|
|
42546
|
+
"Region"
|
|
42547
|
+
];
|
|
42548
|
+
const FEDERATED_DATABASE_MEMBERS = ["ConnectionName", "Identifier"];
|
|
42549
|
+
/**
|
|
42550
|
+
* Is this leaf value one cdkd can put on the wire? A STRING or a NUMBER — CFn
|
|
42551
|
+
* is stringly typed and an unquoted YAML account id arrives as a number (the
|
|
42552
|
+
* reason `catalogIdForApi` exists) — and nothing else, so an unresolved
|
|
42553
|
+
* intrinsic cannot ride an unchecked cast into the request.
|
|
42554
|
+
*/
|
|
42555
|
+
const isSendableLeaf = (value) => typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
42556
|
+
/**
|
|
42557
|
+
* The refusal sentence for a `DatabaseInput` block that IS a plain object and
|
|
42558
|
+
* still names nothing cdkd can send — an unresolved intrinsic or a bare `{}`.
|
|
42559
|
+
* Shared so the create refusal and the update warning cannot drift apart.
|
|
42560
|
+
*/
|
|
42561
|
+
const emptyBlockMessage = (block) => `AWS::Glue::Database DatabaseInput.${block} declares no member cdkd can send (an unresolved intrinsic, an empty block), or mixes sendable members with unreadable ones; sending it would put an empty or NARROWED ${block} on the wire. Where this is only WARNED — an update, or a state replay — the previously applied block is retained if cdkd can still read one, and otherwise the key is omitted, which UpdateDatabase applies as a removal because it replaces DatabaseInput wholesale`;
|
|
42383
42562
|
function asRecord(value) {
|
|
42384
42563
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return;
|
|
42385
42564
|
return value;
|
|
@@ -77006,7 +77185,7 @@ function createMigrateCommand() {
|
|
|
77006
77185
|
*/
|
|
77007
77186
|
function buildProgram() {
|
|
77008
77187
|
const program = new Command();
|
|
77009
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.
|
|
77188
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.283.7");
|
|
77010
77189
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
77011
77190
|
const { profile } = actionCommand.optsWithGlobals();
|
|
77012
77191
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|