@go-to-k/cdkd 0.280.18 → 0.280.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { $ as requireConfigString, $t as processStackMessages, A as red, At as runDockerStreaming, B as isTerminationProtectionPropagationError, Bt as resolveSkipPrefix, C as isStatefulRecreateTargetSync, Ct as parseBootstrapMarker, D as cyan, Dn as normalizeAwsError, Dt as formatDockerLoginError, E as bold, Et as buildDockerImage, F as ProviderRegistry, Ft as getDefaultStateBucketName, G as normalizeAwsTagsToCfn, Gt as warnDeprecatedNoPrefixCliFlag, H as cfnRefValueFromPhysicalId, Ht as resolveStateBucketWithDefaultAndSource, I as findActionableSilentDrops, It as getLegacyStateBucketName, J as configStringRefusal, Jt as MIGRATE_TMP_PREFIX, K as resolveExplicitPhysicalId, Kt as CFN_TEMPLATE_BODY_LIMIT, L as CloudControlProvider, Lt as resolveApp, M as IAMRoleProvider, Mt as getDockerImageBySourceHash, N as collectInlinePolicyNamesManagedBySiblings, Nt as Synthesizer, O as gray, On as withErrorHandling, Ot as getDockerCmd, P as clearOnUpdateRemoval, Pt as synthesisStatusMessage, Q as requireConfigObject, Qt as AssemblyReader, R as slowCcOperationTimeoutMs, Rt as resolveAutoAssetStorage, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as StackTerminationProtectionError, St as getBootstrapMarkerKey, T as formatResourceLine, Tt as validateContainerRepoName, U as refStateLookupFromResource, Ut as resolveUseCdkBootstrapAssets, V as IntrinsicFunctionResolver, Vt as resolveStateBucketWithDefault, W as WAFv2WebACLProvider, Wt as stateBucketExistenceConfirmed, X as replayWarn, Xt as uploadCfnTemplate, Y as readConfigString, Yt as findLargeInlineResources, Z as requireConfigArray, Zt as expectedOwnerParam, _ as createPreDeleteFinalSnapshot, _n as PartialFailureError, _t as loadPublishableAssetManifest, a as DeploymentEventsStore, an as setAwsClients, at as isThrottlingError, b as unsupportedFinalSnapshotError, bn as ResourceUpdateNotSupportedError, bt as BOOTSTRAP_MARKER_PREFIX, c as replayFailedOperations, ct as LockManager, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalInvokeBuildError$1, dt as shouldRetainResource, et as applyRoleArnIfSet, f as computeImplicitDeleteEdges, fn as LocalMigrateError, ft as AssetPublisher, g as ccRoutedFinalSnapshotError, gn as NestedStackChildDirectDestroyError, gt as createAssetRedirectResolver, h as buildFinalSnapshotIdentifier, hn as MissingCdkCliError, ht as buildAssetRedirectMap, i as DeploymentEventsReader, in as resetAwsClients, it as isRetryableTransientError, j as yellow, jt as AssetManifestLoader, k as green, kt as runDockerForeground, l as replayRollback, lt as S3StateBackend, m as PRE_DELETE_SNAPSHOT_TYPES, mt as WorkGraph, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as AwsClients, nt as describeTypeWithThrottleRetry, o as planFailedOps, ot as DagBuilder, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalStartServiceError, pt as stringifyValue, q as assertRegionMatch, qt as CFN_TEMPLATE_URL_LIMIT, r as DeployEngine, rn as getAwsClients, rt as withRetry, s as planRollback, sn as CdkdError, st as TemplateParser, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resolveBucketRegion, tt as DiffCalculator, u as withResourceDeadline, un as DeployCancelledError, ut as rebuildClientForBucketRegion, v as isFinalSnapshotError, vn as ProvisioningError, vt as rewriteTemplateAssetReferences, w as renderStatefulReason, wt as validateAssetBucketName, x as extractDeploymentEventError, xn as StackHasActiveImportsError, xt as ensureAssetStorage, y as refusesFinalSnapshot, yn as ResourceTimeoutError, yt as AssetModeResolver, z as disableInstanceApiTermination, zt as resolveCaptureObservedState } from "./deploy-engine-mvkiu-7h.js";
2
+ import { $ as requireConfigString, $t as processStackMessages, A as red, At as runDockerStreaming, B as isTerminationProtectionPropagationError, Bt as resolveSkipPrefix, C as isStatefulRecreateTargetSync, Ct as parseBootstrapMarker, D as cyan, Dn as normalizeAwsError, Dt as formatDockerLoginError, E as bold, Et as buildDockerImage, F as ProviderRegistry, Ft as getDefaultStateBucketName, G as normalizeAwsTagsToCfn, Gt as warnDeprecatedNoPrefixCliFlag, H as cfnRefValueFromPhysicalId, Ht as resolveStateBucketWithDefaultAndSource, I as findActionableSilentDrops, It as getLegacyStateBucketName, J as configStringRefusal, Jt as MIGRATE_TMP_PREFIX, K as resolveExplicitPhysicalId, Kt as CFN_TEMPLATE_BODY_LIMIT, L as CloudControlProvider, Lt as resolveApp, M as IAMRoleProvider, Mt as getDockerImageBySourceHash, N as collectInlinePolicyNamesManagedBySiblings, Nt as Synthesizer, O as gray, On as withErrorHandling, Ot as getDockerCmd, P as clearOnUpdateRemoval, Pt as synthesisStatusMessage, Q as requireConfigObject, Qt as AssemblyReader, R as slowCcOperationTimeoutMs, Rt as resolveAutoAssetStorage, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as StackTerminationProtectionError, St as getBootstrapMarkerKey, T as formatResourceLine, Tt as validateContainerRepoName, U as refStateLookupFromResource, Ut as resolveUseCdkBootstrapAssets, V as IntrinsicFunctionResolver, Vt as resolveStateBucketWithDefault, W as WAFv2WebACLProvider, Wt as stateBucketExistenceConfirmed, X as replayWarn, Xt as uploadCfnTemplate, Y as readConfigString, Yt as findLargeInlineResources, Z as requireConfigArray, Zt as expectedOwnerParam, _ as createPreDeleteFinalSnapshot, _n as PartialFailureError, _t as loadPublishableAssetManifest, a as DeploymentEventsStore, an as setAwsClients, at as isThrottlingError, b as unsupportedFinalSnapshotError, bn as ResourceUpdateNotSupportedError, bt as BOOTSTRAP_MARKER_PREFIX, c as replayFailedOperations, ct as LockManager, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalInvokeBuildError$1, dt as shouldRetainResource, et as applyRoleArnIfSet, f as computeImplicitDeleteEdges, fn as LocalMigrateError, ft as AssetPublisher, g as ccRoutedFinalSnapshotError, gn as NestedStackChildDirectDestroyError, gt as createAssetRedirectResolver, h as buildFinalSnapshotIdentifier, hn as MissingCdkCliError, ht as buildAssetRedirectMap, i as DeploymentEventsReader, in as resetAwsClients, it as isRetryableTransientError, j as yellow, jt as AssetManifestLoader, k as green, kt as runDockerForeground, l as replayRollback, lt as S3StateBackend, m as PRE_DELETE_SNAPSHOT_TYPES, mt as WorkGraph, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as AwsClients, nt as describeTypeWithThrottleRetry, o as planFailedOps, ot as DagBuilder, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalStartServiceError, pt as stringifyValue, q as assertRegionMatch, qt as CFN_TEMPLATE_URL_LIMIT, r as DeployEngine, rn as getAwsClients, rt as withRetry, s as planRollback, sn as CdkdError, st as TemplateParser, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resolveBucketRegion, tt as DiffCalculator, u as withResourceDeadline, un as DeployCancelledError, ut as rebuildClientForBucketRegion, v as isFinalSnapshotError, vn as ProvisioningError, vt as rewriteTemplateAssetReferences, w as renderStatefulReason, wt as validateAssetBucketName, x as extractDeploymentEventError, xn as StackHasActiveImportsError, xt as ensureAssetStorage, y as refusesFinalSnapshot, yn as ResourceTimeoutError, yt as AssetModeResolver, z as disableInstanceApiTermination, zt as resolveCaptureObservedState } from "./deploy-engine-CC3BV-Gp.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-C6cQkX3h.js";
4
+ import { t as ASGProvider } from "./asg-provider-BWT5cpBO.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";
@@ -49,7 +49,7 @@ import { CreateClusterCommand, CreateServiceCommand, DeleteClusterCommand, Delet
49
49
  import { AddTagsToResourceCommand as AddTagsToResourceCommand$3, CreateDBClusterCommand as CreateDBClusterCommand$1, CreateDBInstanceCommand as CreateDBInstanceCommand$1, CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand$1, DeleteDBClusterCommand as DeleteDBClusterCommand$1, DeleteDBInstanceCommand as DeleteDBInstanceCommand$1, DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand$1, DescribeDBClustersCommand as DescribeDBClustersCommand$1, DescribeDBInstancesCommand as DescribeDBInstancesCommand$1, DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand$1, DocDBClient, ListTagsForResourceCommand as ListTagsForResourceCommand$12, ModifyDBClusterCommand as ModifyDBClusterCommand$1, ModifyDBInstanceCommand as ModifyDBInstanceCommand$1, ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand$1, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$3 } from "@aws-sdk/client-docdb";
50
50
  import { AddTagsToResourceCommand as AddTagsToResourceCommand$4, CreateDBClusterCommand as CreateDBClusterCommand$2, CreateDBInstanceCommand as CreateDBInstanceCommand$2, CreateDBSubnetGroupCommand as CreateDBSubnetGroupCommand$2, DeleteDBClusterCommand as DeleteDBClusterCommand$2, DeleteDBInstanceCommand as DeleteDBInstanceCommand$2, DeleteDBSubnetGroupCommand as DeleteDBSubnetGroupCommand$2, DescribeDBClustersCommand as DescribeDBClustersCommand$2, DescribeDBInstancesCommand as DescribeDBInstancesCommand$2, DescribeDBSubnetGroupsCommand as DescribeDBSubnetGroupsCommand$2, ListTagsForResourceCommand as ListTagsForResourceCommand$13, ModifyDBClusterCommand as ModifyDBClusterCommand$2, ModifyDBInstanceCommand as ModifyDBInstanceCommand$2, ModifyDBSubnetGroupCommand as ModifyDBSubnetGroupCommand$2, NeptuneClient, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$4 } from "@aws-sdk/client-neptune";
51
51
  import { AddCustomAttributesCommand, CognitoIdentityProviderClient, CreateUserPoolCommand, DeleteUserPoolCommand, DescribeUserPoolCommand, GetUserPoolMfaConfigCommand, ListUserPoolsCommand, ResourceNotFoundException as ResourceNotFoundException$9, SetUserPoolMfaConfigCommand, UpdateUserPoolCommand } from "@aws-sdk/client-cognito-identity-provider";
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";
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, ResourceInUse, 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, GetGraphqlApiEnvironmentVariablesCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, NotFoundException as NotFoundException$4, PutGraphqlApiEnvironmentVariablesCommand, 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
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";
@@ -26391,6 +26391,15 @@ const DEPLOYMENT_CONFIG_PRESERVE_KEYS = /* @__PURE__ */ new Set(["HookDetails"])
26391
26391
  */
26392
26392
  const DEPLOYMENT_CONFIG_PRESERVE_KEYS_CAMEL = /* @__PURE__ */ new Set(["hookDetails"]);
26393
26393
  /**
26394
+ * `ServiceConnectConfiguration.LogConfiguration.Options` is a free-form
26395
+ * log-driver option map (e.g. `awslogs-group`) whose keys are user data, NOT
26396
+ * CloudFormation property names — copy the value subtree verbatim while the
26397
+ * `Options` key itself still flips to `options` (issue #609; same rule as
26398
+ * `DEPLOYMENT_CONFIG_PRESERVE_KEYS` above and the container-level
26399
+ * `LogConfiguration.Options` handling in `convertLogConfiguration`).
26400
+ */
26401
+ const SERVICE_CONNECT_PRESERVE_KEYS = /* @__PURE__ */ new Set(["Options"]);
26402
+ /**
26394
26403
  * Derive the cluster name from a long-format ECS Service ARN
26395
26404
  * (`arn:<partition>:ecs:<region>:<account>:service/<clusterName>/<serviceName>`)
26396
26405
  * so `DescribeServices` can be scoped to the right cluster (issue #1170).
@@ -26418,6 +26427,12 @@ function clusterNameFromServiceArn(arn) {
26418
26427
  * The CC API adds unnecessary polling overhead for operations that
26419
26428
  * complete immediately. This SDK provider eliminates that polling.
26420
26429
  */
26430
+ /**
26431
+ * Test seam for `settleService`'s post-stability rollout poll (the sibling of
26432
+ * `finalSnapshotDelays` / `describeTypeRetryDelays`) — tests replace `sleep`
26433
+ * to skip the real 3s waits.
26434
+ */
26435
+ const settleRolloutDelays = { sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
26421
26436
  var ECSProvider = class {
26422
26437
  ecsClient;
26423
26438
  providerRegion = process.env["AWS_REGION"];
@@ -26470,10 +26485,18 @@ var ECSProvider = class {
26470
26485
  "PropagateTags",
26471
26486
  "EnableExecuteCommand",
26472
26487
  "ServiceRegistries",
26473
- "Tags"
26488
+ "Tags",
26489
+ "AvailabilityZoneRebalancing",
26490
+ "DeploymentController",
26491
+ "ForceNewDeployment",
26492
+ "Monitoring",
26493
+ "Role",
26494
+ "ServiceConnectConfiguration",
26495
+ "VolumeConfigurations",
26496
+ "VpcLatticeConfigurations"
26474
26497
  ])]
26475
26498
  ]);
26476
- unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ECS::Service", /* @__PURE__ */ new Map([["Role", "Legacy classic-ELB service-linked-role override; AWS uses the AWSServiceRoleForECS service-linked role automatically since 2017"]])], ["AWS::ECS::TaskDefinition", /* @__PURE__ */ new Map([["InferenceAccelerators", "AWS Elastic Inference end-of-life 2024-04; use AWS Inferentia / Trainium accelerator instance families instead"]])]]);
26499
+ unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ECS::TaskDefinition", /* @__PURE__ */ new Map([["InferenceAccelerators", "AWS Elastic Inference end-of-life 2024-04; use AWS Inferentia / Trainium accelerator instance families instead"]])]]);
26477
26500
  getClient() {
26478
26501
  if (!this.ecsClient) this.ecsClient = new ECSClient(this.providerRegion ? { region: this.providerRegion } : {});
26479
26502
  return this.ecsClient;
@@ -26688,7 +26711,14 @@ var ECSProvider = class {
26688
26711
  propagateTags: properties["PropagateTags"],
26689
26712
  enableExecuteCommand: properties["EnableExecuteCommand"],
26690
26713
  serviceRegistries: this.convertServiceRegistries(properties["ServiceRegistries"]),
26691
- tags: convertTags(properties["Tags"])
26714
+ tags: convertTags(properties["Tags"]),
26715
+ availabilityZoneRebalancing: properties["AvailabilityZoneRebalancing"],
26716
+ deploymentController: this.convertDeploymentController(properties["DeploymentController"]),
26717
+ role: properties["Role"],
26718
+ serviceConnectConfiguration: this.convertServiceConnectConfiguration(properties["ServiceConnectConfiguration"]),
26719
+ volumeConfigurations: this.convertServiceVolumeConfigurations(properties["VolumeConfigurations"]),
26720
+ vpcLatticeConfigurations: this.convertVpcLatticeConfigurations(properties["VpcLatticeConfigurations"]),
26721
+ monitoring: this.convertMonitoringConfiguration(properties["Monitoring"])
26692
26722
  }))).service;
26693
26723
  if (!service || !service.serviceArn) throw new Error("CreateService did not return service ARN");
26694
26724
  this.logger.debug(`Successfully created ECS service ${logicalId}: ${service.serviceArn}`);
@@ -26753,6 +26783,20 @@ var ECSProvider = class {
26753
26783
  cluster,
26754
26784
  services: [serviceRef]
26755
26785
  });
26786
+ const rolloutDeadline = Date.now() + 12e4;
26787
+ for (;;) {
26788
+ const deployments = (await this.getClient().send(new DescribeServicesCommand({
26789
+ cluster,
26790
+ services: [serviceRef]
26791
+ })))?.services?.[0]?.deployments;
26792
+ const rolloutState = deployments && deployments.length === 1 ? deployments[0]?.rolloutState : void 0;
26793
+ if (rolloutState === void 0 || rolloutState === "COMPLETED") break;
26794
+ if (Date.now() >= rolloutDeadline) {
26795
+ this.logger.warn(`ECS service ${logicalId} is steady but its rollout is still ${rolloutState} after the post-stability grace window; continuing`);
26796
+ break;
26797
+ }
26798
+ await settleRolloutDelays.sleep(3e3);
26799
+ }
26756
26800
  this.logger.debug(`ECS service ${logicalId} reached steady state`);
26757
26801
  return;
26758
26802
  }
@@ -26786,6 +26830,13 @@ var ECSProvider = class {
26786
26830
  const enableECSManagedTagsInput = clearOnUpdateRemoval(properties["EnableECSManagedTags"], previousProperties["EnableECSManagedTags"], false);
26787
26831
  const propagateTagsInput = clearOnUpdateRemoval(properties["PropagateTags"], previousProperties["PropagateTags"], "NONE");
26788
26832
  const enableExecuteCommandInput = clearOnUpdateRemoval(properties["EnableExecuteCommand"], previousProperties["EnableExecuteCommand"], false);
26833
+ const availabilityZoneRebalancingInput = JSON.stringify(previousProperties["AvailabilityZoneRebalancing"] ?? null) !== JSON.stringify(properties["AvailabilityZoneRebalancing"] ?? null) && properties["AvailabilityZoneRebalancing"] !== void 0 ? properties["AvailabilityZoneRebalancing"] : void 0;
26834
+ const deploymentControllerInput = JSON.stringify(previousProperties["DeploymentController"] ?? null) !== JSON.stringify(properties["DeploymentController"] ?? null) && properties["DeploymentController"] != null ? this.convertDeploymentController(properties["DeploymentController"]) : void 0;
26835
+ const serviceConnectConfigurationInput = JSON.stringify(previousProperties["ServiceConnectConfiguration"] ?? null) !== JSON.stringify(properties["ServiceConnectConfiguration"] ?? null) ? clearOnUpdateRemoval(this.convertServiceConnectConfiguration(properties["ServiceConnectConfiguration"]), previousProperties["ServiceConnectConfiguration"], { enabled: false }) : void 0;
26836
+ const volumeConfigurationsInput = JSON.stringify(previousProperties["VolumeConfigurations"] ?? null) !== JSON.stringify(properties["VolumeConfigurations"] ?? null) ? clearOnUpdateRemoval(this.convertServiceVolumeConfigurations(properties["VolumeConfigurations"]), previousProperties["VolumeConfigurations"], []) : void 0;
26837
+ const vpcLatticeConfigurationsInput = JSON.stringify(previousProperties["VpcLatticeConfigurations"] ?? null) !== JSON.stringify(properties["VpcLatticeConfigurations"] ?? null) ? clearOnUpdateRemoval(this.convertVpcLatticeConfigurations(properties["VpcLatticeConfigurations"]), previousProperties["VpcLatticeConfigurations"], []) : void 0;
26838
+ const monitoringInput = JSON.stringify(previousProperties["Monitoring"] ?? null) !== JSON.stringify(properties["Monitoring"] ?? null) && properties["Monitoring"] != null ? this.convertMonitoringConfiguration(properties["Monitoring"]) : void 0;
26839
+ const forceNewDeploymentInput = this.resolveForceNewDeployment(properties, previousProperties);
26789
26840
  try {
26790
26841
  const service = (await client.send(new UpdateServiceCommand({
26791
26842
  cluster: properties["Cluster"],
@@ -26803,7 +26854,14 @@ var ECSProvider = class {
26803
26854
  propagateTags: propagateTagsInput,
26804
26855
  enableExecuteCommand: enableExecuteCommandInput,
26805
26856
  loadBalancers: loadBalancersInput,
26806
- serviceRegistries: serviceRegistriesInput
26857
+ serviceRegistries: serviceRegistriesInput,
26858
+ availabilityZoneRebalancing: availabilityZoneRebalancingInput,
26859
+ deploymentController: deploymentControllerInput,
26860
+ serviceConnectConfiguration: serviceConnectConfigurationInput,
26861
+ volumeConfigurations: volumeConfigurationsInput,
26862
+ vpcLatticeConfigurations: vpcLatticeConfigurationsInput,
26863
+ monitoring: monitoringInput,
26864
+ forceNewDeployment: forceNewDeploymentInput
26807
26865
  }))).service;
26808
26866
  if (service?.serviceArn) await this.applyTagDiff(service.serviceArn, previousProperties["Tags"], properties["Tags"]);
26809
26867
  await this.settleService(logicalId, service?.serviceName ?? physicalId, properties["Cluster"]);
@@ -27537,6 +27595,96 @@ var ECSProvider = class {
27537
27595
  return pascalToCamelCaseKeys(items);
27538
27596
  }
27539
27597
  /**
27598
+ * Convert the CFn PascalCase `DeploymentController` block (`{Type}`) to the
27599
+ * ECS SDK camelCase input shape (`{type}`) — a pure first-letter flip
27600
+ * (issue #609).
27601
+ */
27602
+ convertDeploymentController(config) {
27603
+ if (!config) return void 0;
27604
+ return pascalToCamelCaseKeys(config);
27605
+ }
27606
+ /**
27607
+ * Convert the CFn PascalCase `ServiceConnectConfiguration` block to the ECS
27608
+ * SDK camelCase input shape (issue #609). Every key in the subtree is a pure
27609
+ * first-letter flip (`Enabled` / `Namespace` / `Services[].{PortName,
27610
+ * DiscoveryName, ClientAliases, IngressPortOverride, Timeout, Tls}` /
27611
+ * `LogConfiguration` / `AccessLogConfiguration`), so the shared recursive
27612
+ * converter delivers the whole subtree — EXCEPT
27613
+ * `LogConfiguration.Options`, a free-form log-driver option map copied
27614
+ * verbatim (see {@link SERVICE_CONNECT_PRESERVE_KEYS}).
27615
+ */
27616
+ convertServiceConnectConfiguration(config) {
27617
+ if (!config) return void 0;
27618
+ return pascalToCamelCaseKeys(config, SERVICE_CONNECT_PRESERVE_KEYS);
27619
+ }
27620
+ /**
27621
+ * Convert the CFn PascalCase `VolumeConfigurations` array to the ECS SDK
27622
+ * camelCase input shape (issue #609). Every key is a pure first-letter flip
27623
+ * — including the two spellings worth calling out: `ManagedEBSVolume` ->
27624
+ * `managedEBSVolume` and `SizeInGiB` -> `sizeInGiB` (both verified against
27625
+ * the SDK model; only the FIRST character flips, the interior case is
27626
+ * identical), so the shared recursive converter delivers the whole subtree
27627
+ * (`Encrypted` / `KmsKeyId` / `VolumeType` / `SnapshotId` /
27628
+ * `VolumeInitializationRate` / `Iops` / `Throughput` / `TagSpecifications`
27629
+ * / `RoleArn` / `FilesystemType`).
27630
+ */
27631
+ convertServiceVolumeConfigurations(items) {
27632
+ if (!items) return void 0;
27633
+ return pascalToCamelCaseKeys(items);
27634
+ }
27635
+ /**
27636
+ * Convert the CFn PascalCase `VpcLatticeConfigurations` array to the ECS
27637
+ * SDK camelCase input shape (issue #609). Each element `{RoleArn,
27638
+ * TargetGroupArn, PortName}` is a pure first-letter flip.
27639
+ */
27640
+ convertVpcLatticeConfigurations(items) {
27641
+ if (!items) return void 0;
27642
+ return pascalToCamelCaseKeys(items);
27643
+ }
27644
+ /**
27645
+ * Convert the CFn PascalCase `Monitoring` block to the ECS SDK camelCase
27646
+ * `monitoring` input shape (issue #609). Every key is a pure first-letter
27647
+ * flip (`MetricConfigurations[].{MetricNames, ResolutionSeconds}`).
27648
+ */
27649
+ convertMonitoringConfiguration(config) {
27650
+ if (!config) return void 0;
27651
+ return pascalToCamelCaseKeys(config);
27652
+ }
27653
+ /**
27654
+ * Translate the CFn-only `ForceNewDeployment` trigger object
27655
+ * (`{EnableForceNewDeployment, ForceNewDeploymentNonce}`) into the SDK's
27656
+ * plain `forceNewDeployment` boolean on UpdateService (issue #609).
27657
+ *
27658
+ * A forced rollout is requested when EITHER the template says
27659
+ * `EnableForceNewDeployment: true` OR the nonce changed vs the previous
27660
+ * deploy's recorded value (introducing a nonce counts as a change). On any
27661
+ * other shape — block absent, malformed, enable false with an unchanged
27662
+ * nonce — return `undefined` so the field is omitted (AWS's documented
27663
+ * default: deployments are not forced).
27664
+ *
27665
+ * Create-path: deliberate no-op — CreateService has no such member, and the
27666
+ * initial deployment IS a fresh rollout by definition.
27667
+ *
27668
+ * This is UPDATE-path code, so a malformed desired block WARNS and skips
27669
+ * rather than throwing (the config-shape doctrine: a rollback replays
27670
+ * `update()` with a historical state record as the desired bag).
27671
+ */
27672
+ resolveForceNewDeployment(properties, previousProperties) {
27673
+ const desired = properties["ForceNewDeployment"];
27674
+ if (desired == null) return void 0;
27675
+ if (typeof desired !== "object" || Array.isArray(desired)) {
27676
+ this.logger.warn(`AWS::ECS::Service ForceNewDeployment is not an object (got ${Array.isArray(desired) ? "array" : typeof desired}); skipping the forced-rollout translation`);
27677
+ return;
27678
+ }
27679
+ const block = desired;
27680
+ const enable = this.coerceBool(block["EnableForceNewDeployment"]);
27681
+ const nonce = block["ForceNewDeploymentNonce"];
27682
+ const previous = previousProperties["ForceNewDeployment"];
27683
+ const previousNonce = previous != null && typeof previous === "object" && !Array.isArray(previous) ? previous["ForceNewDeploymentNonce"] : void 0;
27684
+ const nonceChanged = nonce !== void 0 && JSON.stringify(nonce) !== JSON.stringify(previousNonce);
27685
+ return enable === true || nonceChanged ? true : void 0;
27686
+ }
27687
+ /**
27540
27688
  * Convert the CFn PascalCase `TaskDefinition.RuntimePlatform` to the ECS SDK
27541
27689
  * camelCase input shape (issue #1165). `{CpuArchitecture,
27542
27690
  * OperatingSystemFamily}` -> `{cpuArchitecture, operatingSystemFamily}`.
@@ -27645,6 +27793,35 @@ var ECSProvider = class {
27645
27793
  return false;
27646
27794
  }
27647
27795
  /**
27796
+ * State property paths `readCurrentState` deliberately cannot read back
27797
+ * from AWS (issue #609) — fed into the drift comparator's `ignorePaths` so
27798
+ * a template that sets them does not phantom-drift as "removed" on every
27799
+ * run:
27800
+ * - `ServiceConnectConfiguration` / `VolumeConfigurations` /
27801
+ * `VpcLatticeConfigurations`: DescribeServices does not return them on
27802
+ * the top-level `Service` shape (they surface only per-deployment
27803
+ * under `deployments[]`, which is rollout metadata, not service
27804
+ * config). `VolumeConfigurations` is also registry-recorded write-only.
27805
+ * - `Monitoring`: not returned by DescribeServices at all.
27806
+ * - `ForceNewDeployment`: a write-only rollout trigger, not persisted
27807
+ * service state.
27808
+ * - `Role`: AWS reports `Service.roleArn` as the service-linked
27809
+ * AWSServiceRoleForECS ARN when the template omits Role, and always as
27810
+ * a full ARN when the template may carry a bare role name — a
27811
+ * mechanical reverse-map would manufacture drift in both directions.
27812
+ */
27813
+ getDriftUnknownPaths(resourceType) {
27814
+ if (resourceType === "AWS::ECS::Service") return [
27815
+ "ServiceConnectConfiguration",
27816
+ "VolumeConfigurations",
27817
+ "VpcLatticeConfigurations",
27818
+ "Monitoring",
27819
+ "ForceNewDeployment",
27820
+ "Role"
27821
+ ];
27822
+ return [];
27823
+ }
27824
+ /**
27648
27825
  * Read the AWS-current ECS resource configuration in CFn-property shape.
27649
27826
  *
27650
27827
  * Dispatches by resource type:
@@ -27748,6 +27925,8 @@ var ECSProvider = class {
27748
27925
  result["PlacementStrategies"] = strategy;
27749
27926
  }
27750
27927
  result["ServiceRegistries"] = camelToPascalCaseKeys(s.serviceRegistries ?? []);
27928
+ if (s.availabilityZoneRebalancing !== void 0) result["AvailabilityZoneRebalancing"] = s.availabilityZoneRebalancing;
27929
+ result["DeploymentController"] = { Type: s.deploymentController?.type ?? "ECS" };
27751
27930
  result["Tags"] = normalizeAwsTagsToCfn(s.tags);
27752
27931
  return result;
27753
27932
  }
@@ -27873,6 +28052,78 @@ const TARGET_GROUP_ATTRIBUTE_DEFAULTS = {
27873
28052
  "proxy_protocol_v2.enabled": "false"
27874
28053
  };
27875
28054
  /**
28055
+ * Documented AWS defaults for the BOOLEAN / ENUM-valued LoadBalancer and
28056
+ * Listener attributes, used to reset a removed `LoadBalancerAttributes` /
28057
+ * `ListenerAttributes` entry.
28058
+ *
28059
+ * Unlike ModifyTargetGroupAttributes — which rejects an empty `Value` for
28060
+ * EVERY key — these two APIs accept `Value: ''` for the numeric and
28061
+ * free-form string attributes and REJECT it only where the value is
28062
+ * validated against a fixed set. Live A/B 2026-08-11 (issue #1609 item 1),
28063
+ * via the `alb` integ's removal phase:
28064
+ *
28065
+ * idle_timeout.timeout_seconds -> `Value: ''` ACCEPTED (numeric)
28066
+ * deletion_protection.enabled -> "The value of 'deletion_protection.enabled'
28067
+ * must be 'true' or 'false', but was ''"
28068
+ * routing.http.response.server.enabled (Listener)
28069
+ * -> same rejection, same shape
28070
+ *
28071
+ * A rejection fails the whole Modify* call, so ONE removed boolean took the
28072
+ * entire deploy down (and then the rollback with it). Hence: send the
28073
+ * documented default for the validated keys, and keep the empty string for
28074
+ * everything else — which is both these APIs' own "clear the override"
28075
+ * signal and the behaviour every non-boolean key already relied on.
28076
+ *
28077
+ * That fallback is the deliberate DIVERGENCE from
28078
+ * TARGET_GROUP_ATTRIBUTE_DEFAULTS, whose unknown-key arm warns and retains:
28079
+ * there the empty string is never valid, here it is valid for the majority
28080
+ * of keys, so falling back to it preserves working behaviour instead of
28081
+ * silently retaining a value the template asked to drop.
28082
+ *
28083
+ * A key is listed ONLY when ONE unconditional default is established for it —
28084
+ * documented in the SDK model, or (for
28085
+ * `routing.http.response.server.enabled`, which the model leaves unstated)
28086
+ * proven by the `alb` integ's live removal readback. Two exclusion classes
28087
+ * matter, and both are the difference between failing loudly and writing a
28088
+ * wrong value silently:
28089
+ *
28090
+ * - **Default depends on the LOAD BALANCER** — `load_balancing.cross_zone.enabled`
28091
+ * is always-on and unconfigurable for an ALB but defaults to false on an
28092
+ * NLB / GWLB, and `ipv6.deny_all_igw_traffic` is "false for internet-facing
28093
+ * load balancers and true for internal load balancers". cdkd knows neither
28094
+ * the type nor the scheme at diff time, so a hardcoded entry would send the
28095
+ * WRONG value for half of all load balancers — and since it is a valid
28096
+ * boolean, AWS accepts it. For `ipv6.deny_all_igw_traffic` that means
28097
+ * silently un-blocking internet-gateway access on an INTERNAL load balancer.
28098
+ * - **No documented default at all** — `dns_record.client_routing_policy`
28099
+ * enumerates its possible values but states no default.
28100
+ *
28101
+ * Both classes keep the empty-string behaviour they have always had, so a
28102
+ * removal there fails loudly (for a validated key) instead of guessing.
28103
+ *
28104
+ * Source: the `@aws-sdk/client-elastic-load-balancing-v2` model docs for
28105
+ * `ModifyLoadBalancerAttributes` / `ModifyListenerAttributes`, checked per key;
28106
+ * `routing.http.response.server.enabled`'s default is additionally LIVE-proven
28107
+ * by the `alb` integ's removal readback rather than taken from the docs.
28108
+ */
28109
+ const LOAD_BALANCER_ATTRIBUTE_DEFAULTS = {
28110
+ "deletion_protection.enabled": "false",
28111
+ "access_logs.s3.enabled": "false",
28112
+ "connection_logs.s3.enabled": "false",
28113
+ "health_check_logs.s3.enabled": "false",
28114
+ "routing.http.desync_mitigation_mode": "defensive",
28115
+ "routing.http.drop_invalid_header_fields.enabled": "false",
28116
+ "routing.http.preserve_host_header.enabled": "false",
28117
+ "routing.http.x_amzn_tls_version_and_cipher_suite.enabled": "false",
28118
+ "routing.http.xff_client_port.enabled": "false",
28119
+ "routing.http.xff_header_processing.mode": "append",
28120
+ "routing.http2.enabled": "true",
28121
+ "waf.fail_open.enabled": "false",
28122
+ "zonal_shift.config.enabled": "false"
28123
+ };
28124
+ /** @see LOAD_BALANCER_ATTRIBUTE_DEFAULTS — same rule, Listener key table. */
28125
+ const LISTENER_ATTRIBUTE_DEFAULTS = { "routing.http.response.server.enabled": "true" };
28126
+ /**
27876
28127
  * AWS ELBv2 Provider
27877
28128
  *
27878
28129
  * Implements resource provisioning for ELBv2 resources:
@@ -28085,7 +28336,7 @@ var ELBv2Provider = class {
28085
28336
  return out;
28086
28337
  };
28087
28338
  if (JSON.stringify(stripHandled(properties)) !== JSON.stringify(stripHandled(previousProperties))) throw new ResourceUpdateNotSupportedError("AWS::ElasticLoadBalancingV2::LoadBalancer", logicalId, "ELBv2 LoadBalancer Name / Type / Scheme are immutable on AWS — none of the ELBv2 Modify* / Set* APIs accept these fields; they are fixed at creation. cdkd handles LoadBalancerAttributes / Subnets / SubnetMappings / SecurityGroups / IpAddressType / Tags in-place; for Name / Type / Scheme re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.");
28088
- const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["LoadBalancerAttributes"]), this.normalizeAttributes(previousProperties["LoadBalancerAttributes"]));
28339
+ const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["LoadBalancerAttributes"]), this.normalizeAttributes(previousProperties["LoadBalancerAttributes"]), this.attributeRemovalResolver(LOAD_BALANCER_ATTRIBUTE_DEFAULTS));
28089
28340
  if (submittedAttrs.length > 0) {
28090
28341
  await this.getClient().send(new ModifyLoadBalancerAttributesCommand({
28091
28342
  LoadBalancerArn: physicalId,
@@ -28309,10 +28560,13 @@ var ELBv2Provider = class {
28309
28560
  UnhealthyThresholdCount: properties["UnhealthyThresholdCount"] !== void 0 ? Number(properties["UnhealthyThresholdCount"]) : void 0,
28310
28561
  ...matcher && { Matcher: matcher }
28311
28562
  }));
28312
- const tgAttrDiff = this.diffAttributes(this.normalizeAttributes(properties["TargetGroupAttributes"]), this.normalizeAttributes(previousProperties["TargetGroupAttributes"]), (key) => {
28313
- const fallback = TARGET_GROUP_ATTRIBUTE_DEFAULTS[key];
28314
- if (fallback === void 0) this.logger.warn(`TargetGroup attribute ${key} was removed from the template but has no documented default cdkd can reset it to — the live value is retained. Set the attribute explicitly to change it.`);
28315
- return fallback;
28563
+ const tgAttrDiff = this.diffAttributes(this.normalizeAttributes(properties["TargetGroupAttributes"]), this.normalizeAttributes(previousProperties["TargetGroupAttributes"]), (key, currentValue) => {
28564
+ const fallback = Object.hasOwn(TARGET_GROUP_ATTRIBUTE_DEFAULTS, key) ? TARGET_GROUP_ATTRIBUTE_DEFAULTS[key] : void 0;
28565
+ if (fallback === void 0) {
28566
+ this.logger.warn(`TargetGroup attribute ${key} was removed from the template but has no documented default cdkd can reset it to — the live value is retained. Set the attribute explicitly to change it.`);
28567
+ return;
28568
+ }
28569
+ return currentValue === fallback ? void 0 : fallback;
28316
28570
  });
28317
28571
  if (tgAttrDiff.length > 0) {
28318
28572
  await this.getClient().send(new ModifyTargetGroupAttributesCommand({
@@ -28444,7 +28698,7 @@ var ELBv2Provider = class {
28444
28698
  ...alpnPolicy && alpnPolicy.length > 0 && { AlpnPolicy: alpnPolicy },
28445
28699
  ...mutualAuth !== void 0 && { MutualAuthentication: mutualAuth }
28446
28700
  }));
28447
- const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["ListenerAttributes"]), this.normalizeAttributes(previousProperties["ListenerAttributes"]));
28701
+ const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["ListenerAttributes"]), this.normalizeAttributes(previousProperties["ListenerAttributes"]), this.attributeRemovalResolver(LISTENER_ATTRIBUTE_DEFAULTS));
28448
28702
  if (submittedAttrs.length > 0) {
28449
28703
  await withRetry(() => this.getClient().send(new ModifyListenerAttributesCommand({
28450
28704
  ListenerArn: physicalId,
@@ -28522,14 +28776,28 @@ var ELBv2Provider = class {
28522
28776
  /**
28523
28777
  * Key-diff two normalized `{Key, Value}` attribute lists into the payload
28524
28778
  * for a Modify*Attributes call: changed values from `newAttrs` win, and
28525
- * keys present only in `oldAttrs` are pushed back through `removalValue` —
28526
- * by default the empty string, which ModifyLoadBalancerAttributes /
28527
- * ModifyListenerAttributes accept as "clear the override". A resolver
28528
- * returning `undefined` SKIPS the entry (the resolver owns any warn).
28529
- * An empty return means nothing changed and the call should be skipped.
28530
- * Shared by the LoadBalancer / TargetGroup / Listener update paths.
28531
- */
28532
- diffAttributes(newAttrs, oldAttrs, removalValue = () => "") {
28779
+ * keys present only in `oldAttrs` are pushed back through `removalValue`.
28780
+ * A resolver returning `undefined` SKIPS the entry (the resolver owns any
28781
+ * warn). An empty return means nothing changed and the call should be
28782
+ * skipped. Shared by the LoadBalancer / TargetGroup / Listener update
28783
+ * paths and all three pass their OWN resolver, because the three APIs
28784
+ * disagree about what resets an attribute:
28785
+ *
28786
+ * - LoadBalancer / Listener: the empty string clears a numeric or
28787
+ * free-form-string override, but a BOOLEAN / ENUM key rejects it and
28788
+ * fails the whole call, so those take a documented default
28789
+ * (`LOAD_BALANCER_ATTRIBUTE_DEFAULTS` / `LISTENER_ATTRIBUTE_DEFAULTS`).
28790
+ * - TargetGroup: the empty string is rejected for EVERY key, so the
28791
+ * documented default is the only reset and an unknown key warns and
28792
+ * retains (`TARGET_GROUP_ATTRIBUTE_DEFAULTS`).
28793
+ *
28794
+ * All three behaviours were live-verified 2026-08-11. `removalValue` is
28795
+ * REQUIRED rather than defaulted: there is no reset value that is correct
28796
+ * for all three APIs, so a caller that forgets to pass one should fail to
28797
+ * compile instead of silently inheriting the empty string that two of the
28798
+ * three reject.
28799
+ */
28800
+ diffAttributes(newAttrs, oldAttrs, removalValue) {
28533
28801
  const newAttrMap = new Map(newAttrs.map((a) => [a.Key, a.Value]));
28534
28802
  const oldAttrMap = new Map(oldAttrs.map((a) => [a.Key, a.Value]));
28535
28803
  const submitted = [];
@@ -28537,8 +28805,8 @@ var ELBv2Provider = class {
28537
28805
  Key: k,
28538
28806
  Value: v
28539
28807
  });
28540
- for (const [k] of oldAttrMap) if (!newAttrMap.has(k)) {
28541
- const value = removalValue(k);
28808
+ for (const [k, currentValue] of oldAttrMap) if (!newAttrMap.has(k)) {
28809
+ const value = removalValue(k, currentValue);
28542
28810
  if (value !== void 0) submitted.push({
28543
28811
  Key: k,
28544
28812
  Value: value
@@ -28547,6 +28815,40 @@ var ELBv2Provider = class {
28547
28815
  return submitted;
28548
28816
  }
28549
28817
  /**
28818
+ * Build the `removalValue` resolver for the LoadBalancer / Listener attribute
28819
+ * arms: reset a removed key to its documented default, or to `''` (which
28820
+ * those two APIs accept as "clear the override") when no default is known.
28821
+ *
28822
+ * **A key already AT its default is SKIPPED, and that is a safety property,
28823
+ * not an optimization.** The previous side is not always a template: `cdkd
28824
+ * drift --revert` calls `update(..., newProperties, outcome.awsProperties)`
28825
+ * (`src/cli/commands/drift.ts`), so `oldAttrs` can be the FULL
28826
+ * `readCurrentState` snapshot — every attribute AWS reports, including the
28827
+ * ~18 the user never templated. Against a state record with no
28828
+ * `observedProperties` the desired side is the template's one or two keys,
28829
+ * so every untemplated key looks REMOVED and would be "reset".
28830
+ *
28831
+ * Writing a documented default there would silently disable deletion
28832
+ * protection, access / connection logs, HTTP/2, WAF fail-open and zonal
28833
+ * shift on a live load balancer. Before the defaults table existed this was
28834
+ * accidentally safe — `''` fails validation, so the whole revert aborted and
28835
+ * changed nothing — so introducing the table without this guard would have
28836
+ * converted a loud refusal into a silent destructive write.
28837
+ *
28838
+ * The skip is exact rather than heuristic: a key the user never templated is
28839
+ * BY DEFINITION sitting at its default, so it is skipped; a key the template
28840
+ * really did set is set to a NON-default value (otherwise templating it
28841
+ * would be a no-op), so its reset still fires. A template that set a key to
28842
+ * exactly its default and then dropped it is skipped too — correctly, since
28843
+ * there is nothing to change.
28844
+ */
28845
+ attributeRemovalResolver(defaults) {
28846
+ return (key, currentValue) => {
28847
+ const fallback = Object.hasOwn(defaults, key) ? defaults[key] : "";
28848
+ return currentValue === fallback ? void 0 : fallback;
28849
+ };
28850
+ }
28851
+ /**
28550
28852
  * Normalize a CFn `Targets` value (an array of `{ Id, Port?,
28551
28853
  * AvailabilityZone? }` objects) into the SDK's `TargetDescription[]` shape.
28552
28854
  * Entries missing an `Id` are dropped (Id is the only required member);
@@ -33987,8 +34289,16 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
33987
34289
  this.logger.debug(`Deleting Cloud Map namespace ${logicalId}: ${physicalId}`);
33988
34290
  const client = this.getClient();
33989
34291
  try {
33990
- const operationId = (await client.send(new DeleteNamespaceCommand({ Id: physicalId }))).OperationId;
33991
- if (operationId) await this.pollOperation(operationId, logicalId, resourceType);
34292
+ await withRetry(async () => {
34293
+ const operationId = (await client.send(new DeleteNamespaceCommand({ Id: physicalId }))).OperationId;
34294
+ if (operationId) await this.pollOperation(operationId, logicalId, resourceType);
34295
+ }, logicalId, {
34296
+ maxRetries: 24,
34297
+ initialDelayMs: 3e3,
34298
+ maxDelayMs: 15e3,
34299
+ isRetryable: (message, error) => error instanceof ResourceInUse || /has associated services/i.test(message),
34300
+ logger: this.logger
34301
+ });
33992
34302
  this.logger.debug(`Successfully deleted Cloud Map namespace ${logicalId}`);
33993
34303
  } catch (error) {
33994
34304
  if (error instanceof NamespaceNotFound) {
@@ -69797,7 +70107,7 @@ function createMigrateCommand() {
69797
70107
  */
69798
70108
  function buildProgram() {
69799
70109
  const program = new Command();
69800
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.18");
70110
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.20");
69801
70111
  program.hook("preAction", (_thisCommand, actionCommand) => {
69802
70112
  const { profile } = actionCommand.optsWithGlobals();
69803
70113
  if (profile !== void 0) process.env["AWS_PROFILE"] = profile;