@go-to-k/cdkd 0.249.0 → 0.251.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { $ as ensureAssetStorage, A as WAFv2WebACLProvider, B as LockManager, Bt as LocalInvokeBuildError$1, C as findActionableSilentDrops, Ct as CFN_TEMPLATE_BODY_LIMIT, D as IntrinsicFunctionResolver, Dt as uploadCfnTemplate, E as isTerminationProtectionPropagationError, Et as findLargeInlineResources, F as assertRegionMatch, Ft as setAwsClients, G as stringifyValue, Gt as NestedStackChildDirectDestroyError, H as rebuildClientForBucketRegion, Ht as LocalStartServiceError, I as applyRoleArnIfSet, J as createAssetRedirectResolver, Jt as ResourceTimeoutError, K as WorkGraph, Kt as PartialFailureError, L as DiffCalculator, Lt as CdkdError, M as matchesCdkPath, Mt as AwsClients, N as normalizeAwsTagsToCfn, Nt as getAwsClients, O as cfnRefValueFromPhysicalId, Ot as expectedOwnerParam, P as resolveExplicitPhysicalId, Pt as resetAwsClients, Q as BOOTSTRAP_MARKER_PREFIX, R as DagBuilder, S as ProviderRegistry, St as warnDeprecatedNoPrefixCliFlag, T as disableInstanceApiTermination, Tt as MIGRATE_TMP_PREFIX, U as shouldRetainResource, V as S3StateBackend, Vt as LocalMigrateError, W as AssetPublisher, Wt as MissingCdkCliError, X as rewriteTemplateAssetReferences, Xt as StackHasActiveImportsError, Y as loadPublishableAssetManifest, Yt as ResourceUpdateNotSupportedError, Z as AssetModeResolver, Zt as StackTerminationProtectionError, _ as green, _t as resolveCaptureObservedState, a as withRetry, at as formatDockerLoginError, b as IAMRoleProvider, bt as resolveStateBucketWithDefaultAndSource, c as computeImplicitDeleteEdges, ct as runDockerStreaming, d as isStatefulRecreateTargetSync, dt as Synthesizer, et as getBootstrapMarkerKey, f as renderStatefulReason, ft as synthesisStatusMessage, g as gray, gt as resolveAutoAssetStorage, h as cyan, ht as resolveApp, i as withResourceDeadline, it as buildDockerImage, j as CDK_PATH_TAG, jt as resolveBucketRegion, k as refStateLookupFromResource, kt as AssemblyReader, l as extractDeploymentEventError, lt as AssetManifestLoader, m as bold, mt as getLegacyStateBucketName, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as normalizeAwsError, nt as validateAssetBucketName, o as isRetryableTransientError, ot as getDockerCmd, p as formatResourceLine, pt as getDefaultStateBucketName, q as buildAssetRedirectMap, qt as ProvisioningError, r as DeployEngine, rn as withErrorHandling, rt as validateContainerRepoName, s as IMPLICIT_DELETE_DEPENDENCIES, st as runDockerForeground, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as parseBootstrapMarker, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, ut as getDockerImageBySourceHash, v as red, vt as resolveSkipPrefix, w as CloudControlProvider, wt as CFN_TEMPLATE_URL_LIMIT, x as collectInlinePolicyNamesManagedBySiblings, xt as resolveUseCdkBootstrapAssets, y as yellow, yt as resolveStateBucketWithDefault, z as TemplateParser } from "./deploy-engine-DqAyGFJu.js";
2
+ import { $ as ensureAssetStorage, A as WAFv2WebACLProvider, B as LockManager, Bt as LocalInvokeBuildError$1, C as findActionableSilentDrops, Ct as CFN_TEMPLATE_BODY_LIMIT, D as IntrinsicFunctionResolver, Dt as uploadCfnTemplate, E as isTerminationProtectionPropagationError, Et as findLargeInlineResources, F as assertRegionMatch, Ft as setAwsClients, G as stringifyValue, Gt as NestedStackChildDirectDestroyError, H as rebuildClientForBucketRegion, Ht as LocalStartServiceError, I as applyRoleArnIfSet, J as createAssetRedirectResolver, Jt as ResourceTimeoutError, K as WorkGraph, Kt as PartialFailureError, L as DiffCalculator, Lt as CdkdError, M as matchesCdkPath, Mt as AwsClients, N as normalizeAwsTagsToCfn, Nt as getAwsClients, O as cfnRefValueFromPhysicalId, Ot as expectedOwnerParam, P as resolveExplicitPhysicalId, Pt as resetAwsClients, Q as BOOTSTRAP_MARKER_PREFIX, R as DagBuilder, S as ProviderRegistry, St as warnDeprecatedNoPrefixCliFlag, T as disableInstanceApiTermination, Tt as MIGRATE_TMP_PREFIX, U as shouldRetainResource, V as S3StateBackend, Vt as LocalMigrateError, W as AssetPublisher, Wt as MissingCdkCliError, X as rewriteTemplateAssetReferences, Xt as StackHasActiveImportsError, Y as loadPublishableAssetManifest, Yt as ResourceUpdateNotSupportedError, Z as AssetModeResolver, Zt as StackTerminationProtectionError, _ as green, _t as resolveCaptureObservedState, a as withRetry, at as formatDockerLoginError, b as IAMRoleProvider, bt as resolveStateBucketWithDefaultAndSource, c as computeImplicitDeleteEdges, ct as runDockerStreaming, d as isStatefulRecreateTargetSync, dt as Synthesizer, et as getBootstrapMarkerKey, f as renderStatefulReason, ft as synthesisStatusMessage, g as gray, gt as resolveAutoAssetStorage, h as cyan, ht as resolveApp, i as withResourceDeadline, it as buildDockerImage, j as CDK_PATH_TAG, jt as resolveBucketRegion, k as refStateLookupFromResource, kt as AssemblyReader, l as extractDeploymentEventError, lt as AssetManifestLoader, m as bold, mt as getLegacyStateBucketName, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as normalizeAwsError, nt as validateAssetBucketName, o as isRetryableTransientError, ot as getDockerCmd, p as formatResourceLine, pt as getDefaultStateBucketName, q as buildAssetRedirectMap, qt as ProvisioningError, r as DeployEngine, rn as withErrorHandling, rt as validateContainerRepoName, s as IMPLICIT_DELETE_DEPENDENCIES, st as runDockerForeground, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as parseBootstrapMarker, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, ut as getDockerImageBySourceHash, v as red, vt as resolveSkipPrefix, w as CloudControlProvider, wt as CFN_TEMPLATE_URL_LIMIT, x as collectInlinePolicyNamesManagedBySiblings, xt as resolveUseCdkBootstrapAssets, y as yellow, yt as resolveStateBucketWithDefault, z as TemplateParser } from "./deploy-engine-D-gBbMiZ.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-CMWe8LlY.js";
4
+ import { t as ASGProvider } from "./asg-provider-er3xGYRo.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, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListDirectoryBucketsCommand, 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";
@@ -57,7 +57,7 @@ import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPer
57
57
  import { CreateScheduleCommand, DeleteScheduleCommand, GetScheduleCommand, ResourceNotFoundException as ResourceNotFoundException$9, SchedulerClient, UpdateScheduleCommand } from "@aws-sdk/client-scheduler";
58
58
  import { AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, PutBackupPolicyCommand, PutFileSystemPolicyCommand, PutLifecycleConfigurationCommand, UpdateFileSystemCommand, UpdateFileSystemProtectionCommand } from "@aws-sdk/client-efs";
59
59
  import { CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$18, UntagResourceCommand as UntagResourceCommand$18, UpdateFileSystemCommand as UpdateFileSystemCommand$1 } from "@aws-sdk/client-fsx";
60
- import { AddTagsCommand as AddTagsCommand$1, DescribeClusterCommand, EMRClient, InvalidRequestException, ListClustersCommand as ListClustersCommand$1, ListInstanceFleetsCommand, ListInstanceGroupsCommand, ModifyClusterCommand, PutAutoTerminationPolicyCommand, PutManagedScalingPolicyCommand, RemoveAutoTerminationPolicyCommand, RemoveManagedScalingPolicyCommand, RemoveTagsCommand as RemoveTagsCommand$1, RunJobFlowCommand, SetTerminationProtectionCommand, SetVisibleToAllUsersCommand, TerminateJobFlowsCommand } from "@aws-sdk/client-emr";
60
+ import { AddInstanceFleetCommand, AddInstanceGroupsCommand, AddTagsCommand as AddTagsCommand$1, DescribeClusterCommand, EMRClient, InvalidRequestException, ListClustersCommand as ListClustersCommand$1, ListInstanceFleetsCommand, ListInstanceGroupsCommand, ModifyClusterCommand, ModifyInstanceFleetCommand, ModifyInstanceGroupsCommand, PutAutoScalingPolicyCommand, PutAutoTerminationPolicyCommand, PutManagedScalingPolicyCommand, RemoveAutoScalingPolicyCommand, RemoveAutoTerminationPolicyCommand, RemoveManagedScalingPolicyCommand, RemoveTagsCommand as RemoveTagsCommand$1, RunJobFlowCommand, SetTerminationProtectionCommand, SetVisibleToAllUsersCommand, TerminateJobFlowsCommand } from "@aws-sdk/client-emr";
61
61
  import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListDeliveryStreamsCommand, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$10, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
62
62
  import { AddTagsCommand as AddTagsCommand$2, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$1, ListTrailsCommand, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$2, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
63
63
  import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ListProjectsCommand, ResourceNotFoundException as ResourceNotFoundException$11, UpdateProjectCommand } from "@aws-sdk/client-codebuild";
@@ -1888,7 +1888,7 @@ const FLUSH_INTERVAL_MS = 2e3;
1888
1888
  const FLUSH_EVENT_THRESHOLD = 50;
1889
1889
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
1890
1890
  function getCdkdVersion() {
1891
- return "0.249.0";
1891
+ return "0.251.0";
1892
1892
  }
1893
1893
  /**
1894
1894
  * Generate a time-sortable unique run id, e.g.
@@ -34410,8 +34410,8 @@ var EFSProvider = class {
34410
34410
  * storage-capacity growth and deletes can take substantially longer —
34411
34411
  * mirror the Custom Resource provider's 1-hour ceiling.
34412
34412
  */
34413
- const DEFAULT_MAX_WAIT_MS$1 = 3600 * 1e3;
34414
- const DEFAULT_POLL_INTERVAL_MS$1 = 15e3;
34413
+ const DEFAULT_MAX_WAIT_MS$3 = 3600 * 1e3;
34414
+ const DEFAULT_POLL_INTERVAL_MS$3 = 15e3;
34415
34415
  /**
34416
34416
  * Lustre sub-properties that `UpdateFileSystem` accepts (the mutable
34417
34417
  * subset of the CFn `LustreConfiguration` block). Everything else in the
@@ -34494,6 +34494,11 @@ const VARIANT_CONFIG_KEY = {
34494
34494
  ONTAP: "OntapConfiguration",
34495
34495
  OPENZFS: "OpenZFSConfiguration"
34496
34496
  };
34497
+ /**
34498
+ * Exported so a unit test can assert every declared-mutable sub-property has
34499
+ * a matching `apply*UpdateField` case — the invariant the unreachable
34500
+ * `default:` guard enforces at runtime.
34501
+ */
34497
34502
  const VARIANT_MUTABLE_SUBPROPS = {
34498
34503
  LustreConfiguration: LUSTRE_MUTABLE_SUBPROPS,
34499
34504
  WindowsConfiguration: WINDOWS_MUTABLE_SUBPROPS,
@@ -34501,6 +34506,21 @@ const VARIANT_MUTABLE_SUBPROPS = {
34501
34506
  OpenZFSConfiguration: OPENZFS_MUTABLE_SUBPROPS
34502
34507
  };
34503
34508
  /**
34509
+ * Copy `value` into `target[key]` only when AWS actually returned it, so the
34510
+ * snapshot carries no `undefined`-valued keys.
34511
+ *
34512
+ * The drift comparator walks the BASELINE's keys (`observedProperties`, or
34513
+ * `properties` when a resource predates observed-capture), not the AWS side —
34514
+ * so an omitted key here is not itself phantom drift. It matters because this
34515
+ * snapshot BECOMES the next baseline: `deploy-engine` stores it as
34516
+ * `observedProperties`, and an explicit `Foo: undefined` would then be walked
34517
+ * as a real key on every later comparison. Omitting is also what keeps the
34518
+ * emitted shape a faithful subset of the CFn input shape.
34519
+ */
34520
+ const putIfDefined = (target, key, value) => {
34521
+ if (value !== void 0) target[key] = value;
34522
+ };
34523
+ /**
34504
34524
  * Compute the Add/Remove route-table-id deltas an ONTAP / OpenZFS
34505
34525
  * `UpdateFileSystem` needs from the previous vs. next `RouteTableIds` list.
34506
34526
  * Route table membership is an unordered set, so a pure reorder yields no
@@ -34530,7 +34550,7 @@ const TOP_LEVEL_IMMUTABLE_PROPS = [
34530
34550
  "KmsKeyId",
34531
34551
  "BackupId"
34532
34552
  ];
34533
- const toNumber$1 = (v) => v === void 0 ? void 0 : Number(v);
34553
+ const toNumber$3 = (v) => v === void 0 ? void 0 : Number(v);
34534
34554
  const toBoolean$1 = (v) => {
34535
34555
  if (v === void 0) return void 0;
34536
34556
  if (typeof v === "string") return v === "true";
@@ -34581,8 +34601,8 @@ var FSxFileSystemProvider = class {
34581
34601
  pollIntervalMs;
34582
34602
  maxWaitMs;
34583
34603
  constructor(options) {
34584
- this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS$1;
34585
- this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS$1;
34604
+ this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS$3;
34605
+ this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS$3;
34586
34606
  }
34587
34607
  handledProperties = /* @__PURE__ */ new Map([["AWS::FSx::FileSystem", /* @__PURE__ */ new Set([
34588
34608
  "BackupId",
@@ -34635,7 +34655,7 @@ var FSxFileSystemProvider = class {
34635
34655
  SecurityGroupIds: properties["SecurityGroupIds"],
34636
34656
  KmsKeyId: properties["KmsKeyId"],
34637
34657
  StorageType: properties["StorageType"],
34638
- StorageCapacity: toNumber$1(properties["StorageCapacity"]),
34658
+ StorageCapacity: toNumber$3(properties["StorageCapacity"]),
34639
34659
  FileSystemTypeVersion: properties["FileSystemTypeVersion"],
34640
34660
  NetworkType: properties["NetworkType"],
34641
34661
  LustreConfiguration: this.toCreateLustreConfiguration(properties["LustreConfiguration"]),
@@ -34691,24 +34711,24 @@ var FSxFileSystemProvider = class {
34691
34711
  WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
34692
34712
  ImportPath: config["ImportPath"],
34693
34713
  ExportPath: config["ExportPath"],
34694
- ImportedFileChunkSize: toNumber$1(config["ImportedFileChunkSize"]),
34714
+ ImportedFileChunkSize: toNumber$3(config["ImportedFileChunkSize"]),
34695
34715
  DeploymentType: config["DeploymentType"],
34696
34716
  AutoImportPolicy: config["AutoImportPolicy"],
34697
- PerUnitStorageThroughput: toNumber$1(config["PerUnitStorageThroughput"]),
34717
+ PerUnitStorageThroughput: toNumber$3(config["PerUnitStorageThroughput"]),
34698
34718
  DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
34699
- AutomaticBackupRetentionDays: toNumber$1(config["AutomaticBackupRetentionDays"]),
34719
+ AutomaticBackupRetentionDays: toNumber$3(config["AutomaticBackupRetentionDays"]),
34700
34720
  CopyTagsToBackups: toBoolean$1(config["CopyTagsToBackups"]),
34701
34721
  DriveCacheType: config["DriveCacheType"],
34702
34722
  DataCompressionType: config["DataCompressionType"],
34703
34723
  EfaEnabled: toBoolean$1(config["EfaEnabled"]),
34704
- ThroughputCapacity: toNumber$1(config["ThroughputCapacity"]),
34724
+ ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
34705
34725
  MetadataConfiguration: metadata ? {
34706
34726
  Mode: metadata["Mode"],
34707
- Iops: toNumber$1(metadata["Iops"])
34727
+ Iops: toNumber$3(metadata["Iops"])
34708
34728
  } : void 0,
34709
34729
  DataReadCacheConfiguration: readCache ? {
34710
34730
  SizingMode: readCache["SizingMode"],
34711
- SizeGiB: toNumber$1(readCache["SizeGiB"])
34731
+ SizeGiB: toNumber$3(readCache["SizeGiB"])
34712
34732
  } : void 0
34713
34733
  };
34714
34734
  }
@@ -34720,10 +34740,10 @@ var FSxFileSystemProvider = class {
34720
34740
  SelfManagedActiveDirectoryConfiguration: this.toSelfManagedAdConfiguration(config["SelfManagedActiveDirectoryConfiguration"]),
34721
34741
  DeploymentType: config["DeploymentType"],
34722
34742
  PreferredSubnetId: config["PreferredSubnetId"],
34723
- ThroughputCapacity: toNumber$1(config["ThroughputCapacity"]),
34743
+ ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
34724
34744
  WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
34725
34745
  DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
34726
- AutomaticBackupRetentionDays: toNumber$1(config["AutomaticBackupRetentionDays"]),
34746
+ AutomaticBackupRetentionDays: toNumber$3(config["AutomaticBackupRetentionDays"]),
34727
34747
  CopyTagsToBackups: toBoolean$1(config["CopyTagsToBackups"]),
34728
34748
  Aliases: config["Aliases"],
34729
34749
  AuditLogConfiguration: this.toWindowsAuditLogConfiguration(config["AuditLogConfiguration"]),
@@ -34735,7 +34755,7 @@ var FSxFileSystemProvider = class {
34735
34755
  toCreateOntapConfiguration(config) {
34736
34756
  if (!config) return void 0;
34737
34757
  return {
34738
- AutomaticBackupRetentionDays: toNumber$1(config["AutomaticBackupRetentionDays"]),
34758
+ AutomaticBackupRetentionDays: toNumber$3(config["AutomaticBackupRetentionDays"]),
34739
34759
  DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
34740
34760
  DeploymentType: config["DeploymentType"],
34741
34761
  EndpointIpAddressRange: config["EndpointIpAddressRange"],
@@ -34743,10 +34763,10 @@ var FSxFileSystemProvider = class {
34743
34763
  DiskIopsConfiguration: this.toDiskIopsConfiguration(config["DiskIopsConfiguration"]),
34744
34764
  PreferredSubnetId: config["PreferredSubnetId"],
34745
34765
  RouteTableIds: config["RouteTableIds"],
34746
- ThroughputCapacity: toNumber$1(config["ThroughputCapacity"]),
34766
+ ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
34747
34767
  WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
34748
- HAPairs: toNumber$1(config["HAPairs"]),
34749
- ThroughputCapacityPerHAPair: toNumber$1(config["ThroughputCapacityPerHAPair"]),
34768
+ HAPairs: toNumber$3(config["HAPairs"]),
34769
+ ThroughputCapacityPerHAPair: toNumber$3(config["ThroughputCapacityPerHAPair"]),
34750
34770
  EndpointIpv6AddressRange: config["EndpointIpv6AddressRange"]
34751
34771
  };
34752
34772
  }
@@ -34754,12 +34774,12 @@ var FSxFileSystemProvider = class {
34754
34774
  toCreateOpenZFSConfiguration(config) {
34755
34775
  if (!config) return void 0;
34756
34776
  return {
34757
- AutomaticBackupRetentionDays: toNumber$1(config["AutomaticBackupRetentionDays"]),
34777
+ AutomaticBackupRetentionDays: toNumber$3(config["AutomaticBackupRetentionDays"]),
34758
34778
  CopyTagsToBackups: toBoolean$1(config["CopyTagsToBackups"]),
34759
34779
  CopyTagsToVolumes: toBoolean$1(config["CopyTagsToVolumes"]),
34760
34780
  DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
34761
34781
  DeploymentType: config["DeploymentType"],
34762
- ThroughputCapacity: toNumber$1(config["ThroughputCapacity"]),
34782
+ ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
34763
34783
  WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
34764
34784
  DiskIopsConfiguration: this.toDiskIopsConfiguration(config["DiskIopsConfiguration"]),
34765
34785
  RootVolumeConfiguration: this.toOpenZFSRootVolumeConfiguration(config["RootVolumeConfiguration"]),
@@ -34774,7 +34794,7 @@ var FSxFileSystemProvider = class {
34774
34794
  if (!config) return void 0;
34775
34795
  return {
34776
34796
  Mode: config["Mode"],
34777
- Iops: toNumber$1(config["Iops"])
34797
+ Iops: toNumber$3(config["Iops"])
34778
34798
  };
34779
34799
  }
34780
34800
  toSelfManagedAdConfiguration(config) {
@@ -34821,7 +34841,7 @@ var FSxFileSystemProvider = class {
34821
34841
  const nfsExports = config["NfsExports"];
34822
34842
  const quotas = config["UserAndGroupQuotas"];
34823
34843
  return {
34824
- RecordSizeKiB: toNumber$1(config["RecordSizeKiB"]),
34844
+ RecordSizeKiB: toNumber$3(config["RecordSizeKiB"]),
34825
34845
  DataCompressionType: config["DataCompressionType"],
34826
34846
  NfsExports: nfsExports?.map((exp) => ({ ClientConfigurations: (exp["ClientConfigurations"] ?? []).map((cc) => ({
34827
34847
  Clients: cc["Clients"],
@@ -34829,8 +34849,8 @@ var FSxFileSystemProvider = class {
34829
34849
  })) })),
34830
34850
  UserAndGroupQuotas: quotas?.map((q) => ({
34831
34851
  Type: q["Type"],
34832
- Id: toNumber$1(q["Id"]),
34833
- StorageCapacityQuotaGiB: toNumber$1(q["StorageCapacityQuotaGiB"])
34852
+ Id: toNumber$3(q["Id"]),
34853
+ StorageCapacityQuotaGiB: toNumber$3(q["StorageCapacityQuotaGiB"])
34834
34854
  })),
34835
34855
  CopyTagsToSnapshots: toBoolean$1(config["CopyTagsToSnapshots"]),
34836
34856
  ReadOnly: toBoolean$1(config["ReadOnly"])
@@ -34840,7 +34860,7 @@ var FSxFileSystemProvider = class {
34840
34860
  if (!config) return void 0;
34841
34861
  return {
34842
34862
  SizingMode: config["SizingMode"],
34843
- SizeGiB: toNumber$1(config["SizeGiB"])
34863
+ SizeGiB: toNumber$3(config["SizeGiB"])
34844
34864
  };
34845
34865
  }
34846
34866
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
@@ -34875,7 +34895,7 @@ var FSxFileSystemProvider = class {
34875
34895
  const callTimeMs = Date.now();
34876
34896
  const respPendingActions = ((await this.getClient().send(new UpdateFileSystemCommand$1({
34877
34897
  FileSystemId: physicalId,
34878
- ...storageCapacityChanged && { StorageCapacity: toNumber$1(properties["StorageCapacity"]) },
34898
+ ...storageCapacityChanged && { StorageCapacity: toNumber$3(properties["StorageCapacity"]) },
34879
34899
  ...storageTypeChanged && { StorageType: properties["StorageType"] },
34880
34900
  ...typeVersionChanged && { FileSystemTypeVersion: properties["FileSystemTypeVersion"] },
34881
34901
  ...networkTypeChanged && { NetworkType: properties["NetworkType"] },
@@ -34927,14 +34947,30 @@ var FSxFileSystemProvider = class {
34927
34947
  const prevVal = prev[key];
34928
34948
  if (JSON.stringify(nextVal) === JSON.stringify(prevVal)) continue;
34929
34949
  if (!mutable.has(key)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS FSx FileSystem ${configKey}.${key} is immutable on AWS — UpdateFileSystem cannot change it after creation. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
34930
- if (configKey === "LustreConfiguration" ? this.applyLustreUpdateField(key, nextVal, diff) : configKey === "WindowsConfiguration" ? this.applyWindowsUpdateField(key, nextVal, diff) : configKey === "OntapConfiguration" ? this.applyOntapUpdateField(key, nextVal, prevVal, diff) : this.applyOpenZFSUpdateField(key, nextVal, prevVal, diff)) hasMutableDiff = true;
34950
+ const ctx = {
34951
+ resourceType,
34952
+ logicalId,
34953
+ configKey
34954
+ };
34955
+ if (configKey === "LustreConfiguration" ? this.applyLustreUpdateField(ctx, key, nextVal, diff) : configKey === "WindowsConfiguration" ? this.applyWindowsUpdateField(ctx, key, nextVal, diff) : configKey === "OntapConfiguration" ? this.applyOntapUpdateField(ctx, key, nextVal, prevVal, diff) : this.applyOpenZFSUpdateField(ctx, key, nextVal, prevVal, diff)) hasMutableDiff = true;
34931
34956
  }
34932
34957
  return {
34933
34958
  diff,
34934
34959
  hasMutableDiff
34935
34960
  };
34936
34961
  }
34937
- applyLustreUpdateField(key, next, diff) {
34962
+ /**
34963
+ * A sub-property listed in a `*_MUTABLE_SUBPROPS` set with no matching
34964
+ * `apply*UpdateField` case. Reaching here is a cdkd bug, not user error:
34965
+ * `computeVariantConfigDiff` already accepted the key as mutable, so
34966
+ * falling through would issue a no-op `UpdateFileSystem` (`hasMutableDiff`
34967
+ * true, empty diff) and silently drop the user's change. Fail loudly
34968
+ * instead so the missing mapping surfaces the moment it is added.
34969
+ */
34970
+ unmappedMutableSubprop(ctx, key) {
34971
+ throw new ProvisioningError(`AWS FSx FileSystem ${ctx.configKey}.${key} is declared mutable but has no UpdateFileSystem mapping in cdkd. This is a cdkd bug — please report it at https://github.com/go-to-k/cdkd/issues`, ctx.resourceType, ctx.logicalId);
34972
+ }
34973
+ applyLustreUpdateField(ctx, key, next, diff) {
34938
34974
  const out = diff;
34939
34975
  switch (key) {
34940
34976
  case "WeeklyMaintenanceStartTime":
@@ -34944,7 +34980,7 @@ var FSxFileSystemProvider = class {
34944
34980
  case "AutomaticBackupRetentionDays":
34945
34981
  case "PerUnitStorageThroughput":
34946
34982
  case "ThroughputCapacity":
34947
- diff[key] = toNumber$1(next);
34983
+ diff[key] = toNumber$3(next);
34948
34984
  break;
34949
34985
  case "AutoImportPolicy":
34950
34986
  case "DataCompressionType":
@@ -34954,7 +34990,7 @@ var FSxFileSystemProvider = class {
34954
34990
  const metadata = next;
34955
34991
  out.MetadataConfiguration = metadata ? {
34956
34992
  Mode: metadata["Mode"],
34957
- Iops: toNumber$1(metadata["Iops"])
34993
+ Iops: toNumber$3(metadata["Iops"])
34958
34994
  } : void 0;
34959
34995
  break;
34960
34996
  }
@@ -34962,14 +34998,15 @@ var FSxFileSystemProvider = class {
34962
34998
  const readCache = next;
34963
34999
  out.DataReadCacheConfiguration = readCache ? {
34964
35000
  SizingMode: readCache["SizingMode"],
34965
- SizeGiB: toNumber$1(readCache["SizeGiB"])
35001
+ SizeGiB: toNumber$3(readCache["SizeGiB"])
34966
35002
  } : void 0;
34967
35003
  break;
34968
35004
  }
35005
+ default: this.unmappedMutableSubprop(ctx, key);
34969
35006
  }
34970
35007
  return true;
34971
35008
  }
34972
- applyWindowsUpdateField(key, next, diff) {
35009
+ applyWindowsUpdateField(ctx, key, next, diff) {
34973
35010
  const out = diff;
34974
35011
  switch (key) {
34975
35012
  case "WeeklyMaintenanceStartTime":
@@ -34978,7 +35015,7 @@ var FSxFileSystemProvider = class {
34978
35015
  break;
34979
35016
  case "AutomaticBackupRetentionDays":
34980
35017
  case "ThroughputCapacity":
34981
- diff[key] = toNumber$1(next);
35018
+ diff[key] = toNumber$3(next);
34982
35019
  break;
34983
35020
  case "SelfManagedActiveDirectoryConfiguration":
34984
35021
  out.SelfManagedActiveDirectoryConfiguration = this.toSelfManagedAdConfigurationUpdates(next);
@@ -34992,10 +35029,11 @@ var FSxFileSystemProvider = class {
34992
35029
  case "FsrmConfiguration":
34993
35030
  out.FsrmConfiguration = this.toWindowsFsrmConfiguration(next);
34994
35031
  break;
35032
+ default: this.unmappedMutableSubprop(ctx, key);
34995
35033
  }
34996
35034
  return true;
34997
35035
  }
34998
- applyOntapUpdateField(key, next, prev, diff) {
35036
+ applyOntapUpdateField(ctx, key, next, prev, diff) {
34999
35037
  const out = diff;
35000
35038
  switch (key) {
35001
35039
  case "DailyAutomaticBackupStartTime":
@@ -35008,7 +35046,7 @@ var FSxFileSystemProvider = class {
35008
35046
  case "ThroughputCapacity":
35009
35047
  case "ThroughputCapacityPerHAPair":
35010
35048
  case "HAPairs":
35011
- diff[key] = toNumber$1(next);
35049
+ diff[key] = toNumber$3(next);
35012
35050
  break;
35013
35051
  case "DiskIopsConfiguration":
35014
35052
  out.DiskIopsConfiguration = this.toDiskIopsConfiguration(next);
@@ -35019,10 +35057,11 @@ var FSxFileSystemProvider = class {
35019
35057
  if (remove) out.RemoveRouteTableIds = remove;
35020
35058
  return add !== void 0 || remove !== void 0;
35021
35059
  }
35060
+ default: this.unmappedMutableSubprop(ctx, key);
35022
35061
  }
35023
35062
  return true;
35024
35063
  }
35025
- applyOpenZFSUpdateField(key, next, prev, diff) {
35064
+ applyOpenZFSUpdateField(ctx, key, next, prev, diff) {
35026
35065
  const out = diff;
35027
35066
  switch (key) {
35028
35067
  case "DailyAutomaticBackupStartTime":
@@ -35036,7 +35075,7 @@ var FSxFileSystemProvider = class {
35036
35075
  break;
35037
35076
  case "AutomaticBackupRetentionDays":
35038
35077
  case "ThroughputCapacity":
35039
- diff[key] = toNumber$1(next);
35078
+ diff[key] = toNumber$3(next);
35040
35079
  break;
35041
35080
  case "DiskIopsConfiguration":
35042
35081
  out.DiskIopsConfiguration = this.toDiskIopsConfiguration(next);
@@ -35050,6 +35089,7 @@ var FSxFileSystemProvider = class {
35050
35089
  if (remove) out.RemoveRouteTableIds = remove;
35051
35090
  return add !== void 0 || remove !== void 0;
35052
35091
  }
35092
+ default: this.unmappedMutableSubprop(ctx, key);
35053
35093
  }
35054
35094
  return true;
35055
35095
  }
@@ -35223,28 +35263,122 @@ var FSxFileSystemProvider = class {
35223
35263
  default: return;
35224
35264
  }
35225
35265
  }
35266
+ /** Map the read-side `WindowsConfiguration` back to CFn input shape. */
35267
+ readWindowsConfiguration(windows) {
35268
+ const config = {};
35269
+ putIfDefined(config, "ActiveDirectoryId", windows.ActiveDirectoryId);
35270
+ putIfDefined(config, "DeploymentType", windows.DeploymentType);
35271
+ putIfDefined(config, "PreferredSubnetId", windows.PreferredSubnetId);
35272
+ putIfDefined(config, "ThroughputCapacity", windows.ThroughputCapacity);
35273
+ putIfDefined(config, "WeeklyMaintenanceStartTime", windows.WeeklyMaintenanceStartTime);
35274
+ putIfDefined(config, "DailyAutomaticBackupStartTime", windows.DailyAutomaticBackupStartTime);
35275
+ putIfDefined(config, "AutomaticBackupRetentionDays", windows.AutomaticBackupRetentionDays);
35276
+ putIfDefined(config, "CopyTagsToBackups", windows.CopyTagsToBackups);
35277
+ if (windows.Aliases !== void 0) config["Aliases"] = windows.Aliases.map((alias) => alias.Name).filter((name) => name !== void 0);
35278
+ if (windows.SelfManagedActiveDirectoryConfiguration) {
35279
+ const ad = windows.SelfManagedActiveDirectoryConfiguration;
35280
+ const adConfig = {};
35281
+ putIfDefined(adConfig, "DomainName", ad.DomainName);
35282
+ putIfDefined(adConfig, "OrganizationalUnitDistinguishedName", ad.OrganizationalUnitDistinguishedName);
35283
+ putIfDefined(adConfig, "FileSystemAdministratorsGroup", ad.FileSystemAdministratorsGroup);
35284
+ putIfDefined(adConfig, "UserName", ad.UserName);
35285
+ putIfDefined(adConfig, "DnsIps", ad.DnsIps ? [...ad.DnsIps] : void 0);
35286
+ putIfDefined(adConfig, "DomainJoinServiceAccountSecret", ad.DomainJoinServiceAccountSecret);
35287
+ if (Object.keys(adConfig).length > 0) config["SelfManagedActiveDirectoryConfiguration"] = adConfig;
35288
+ }
35289
+ if (windows.AuditLogConfiguration) {
35290
+ const audit = {};
35291
+ putIfDefined(audit, "FileAccessAuditLogLevel", windows.AuditLogConfiguration.FileAccessAuditLogLevel);
35292
+ putIfDefined(audit, "FileShareAccessAuditLogLevel", windows.AuditLogConfiguration.FileShareAccessAuditLogLevel);
35293
+ putIfDefined(audit, "AuditLogDestination", windows.AuditLogConfiguration.AuditLogDestination);
35294
+ if (Object.keys(audit).length > 0) config["AuditLogConfiguration"] = audit;
35295
+ }
35296
+ const diskIops = this.readDiskIopsConfiguration(windows.DiskIopsConfiguration);
35297
+ if (diskIops) config["DiskIopsConfiguration"] = diskIops;
35298
+ if (windows.FsrmConfiguration) {
35299
+ const fsrm = {};
35300
+ putIfDefined(fsrm, "FsrmServiceEnabled", windows.FsrmConfiguration.FsrmServiceEnabled);
35301
+ putIfDefined(fsrm, "EventLogDestination", windows.FsrmConfiguration.EventLogDestination);
35302
+ if (Object.keys(fsrm).length > 0) config["FsrmConfiguration"] = fsrm;
35303
+ }
35304
+ return config;
35305
+ }
35306
+ /** Map the read-side `OntapConfiguration` back to CFn input shape. */
35307
+ readOntapConfiguration(ontap) {
35308
+ const config = {};
35309
+ putIfDefined(config, "DeploymentType", ontap.DeploymentType);
35310
+ putIfDefined(config, "AutomaticBackupRetentionDays", ontap.AutomaticBackupRetentionDays);
35311
+ putIfDefined(config, "DailyAutomaticBackupStartTime", ontap.DailyAutomaticBackupStartTime);
35312
+ putIfDefined(config, "WeeklyMaintenanceStartTime", ontap.WeeklyMaintenanceStartTime);
35313
+ putIfDefined(config, "EndpointIpAddressRange", ontap.EndpointIpAddressRange);
35314
+ putIfDefined(config, "PreferredSubnetId", ontap.PreferredSubnetId);
35315
+ putIfDefined(config, "ThroughputCapacity", ontap.ThroughputCapacity);
35316
+ putIfDefined(config, "ThroughputCapacityPerHAPair", ontap.ThroughputCapacityPerHAPair);
35317
+ putIfDefined(config, "HAPairs", ontap.HAPairs);
35318
+ putIfDefined(config, "RouteTableIds", ontap.RouteTableIds ? [...ontap.RouteTableIds] : void 0);
35319
+ putIfDefined(config, "EndpointIpv6AddressRange", ontap.EndpointIpv6AddressRange);
35320
+ const diskIops = this.readDiskIopsConfiguration(ontap.DiskIopsConfiguration);
35321
+ if (diskIops) config["DiskIopsConfiguration"] = diskIops;
35322
+ return config;
35323
+ }
35324
+ /** Map the read-side `OpenZFSConfiguration` back to CFn input shape. */
35325
+ readOpenZFSConfiguration(openzfs) {
35326
+ const config = {};
35327
+ putIfDefined(config, "DeploymentType", openzfs.DeploymentType);
35328
+ putIfDefined(config, "AutomaticBackupRetentionDays", openzfs.AutomaticBackupRetentionDays);
35329
+ putIfDefined(config, "CopyTagsToBackups", openzfs.CopyTagsToBackups);
35330
+ putIfDefined(config, "CopyTagsToVolumes", openzfs.CopyTagsToVolumes);
35331
+ putIfDefined(config, "DailyAutomaticBackupStartTime", openzfs.DailyAutomaticBackupStartTime);
35332
+ putIfDefined(config, "WeeklyMaintenanceStartTime", openzfs.WeeklyMaintenanceStartTime);
35333
+ putIfDefined(config, "ThroughputCapacity", openzfs.ThroughputCapacity);
35334
+ putIfDefined(config, "PreferredSubnetId", openzfs.PreferredSubnetId);
35335
+ putIfDefined(config, "EndpointIpAddressRange", openzfs.EndpointIpAddressRange);
35336
+ putIfDefined(config, "RouteTableIds", openzfs.RouteTableIds ? [...openzfs.RouteTableIds] : void 0);
35337
+ putIfDefined(config, "EndpointIpv6AddressRange", openzfs.EndpointIpv6AddressRange);
35338
+ const diskIops = this.readDiskIopsConfiguration(openzfs.DiskIopsConfiguration);
35339
+ if (diskIops) config["DiskIopsConfiguration"] = diskIops;
35340
+ if (openzfs.ReadCacheConfiguration) {
35341
+ const readCache = {};
35342
+ putIfDefined(readCache, "SizingMode", openzfs.ReadCacheConfiguration.SizingMode);
35343
+ putIfDefined(readCache, "SizeGiB", openzfs.ReadCacheConfiguration.SizeGiB);
35344
+ if (Object.keys(readCache).length > 0) config["ReadCacheConfiguration"] = readCache;
35345
+ }
35346
+ return config;
35347
+ }
35348
+ /** Shared `DiskIopsConfiguration` reverse-mapper (Windows / ONTAP / OpenZFS). */
35349
+ readDiskIopsConfiguration(diskIops) {
35350
+ if (!diskIops) return void 0;
35351
+ const out = {};
35352
+ putIfDefined(out, "Mode", diskIops.Mode);
35353
+ putIfDefined(out, "Iops", diskIops.Iops);
35354
+ return Object.keys(out).length > 0 ? out : void 0;
35355
+ }
35226
35356
  /**
35227
35357
  * State property paths this provider cannot read back from AWS:
35228
35358
  * - `SecurityGroupIds` — `DescribeFileSystems` returns network
35229
35359
  * interface ids, never the original security group list.
35230
35360
  * - `BackupId` — creation-source input, not surfaced on the deployed
35231
35361
  * file system.
35232
- * - `WindowsConfiguration` / `OntapConfiguration` / `OpenZFSConfiguration`
35233
- * `readCurrentState` maps only the Lustre block back to CFn shape
35234
- * today, so drift on the non-Lustre variant blocks is not yet computed;
35235
- * marking them unknown avoids a guaranteed false positive on every run
35236
- * (variant-config drift is a follow-up). Only the block matching the
35237
- * file system's type is ever present in state, so listing all three is
35238
- * harmless.
35362
+ * - `WindowsConfiguration.SelfManagedActiveDirectoryConfiguration.Password`
35363
+ * / `OntapConfiguration.FsxAdminPassword` write-only credentials; the
35364
+ * API never echoes them back.
35365
+ * - `OpenZFSConfiguration.RootVolumeConfiguration` configured on the
35366
+ * root VOLUME, not the file system; `DescribeFileSystems` returns only
35367
+ * `RootVolumeId`, so reading it back would need a separate
35368
+ * `DescribeVolumes` call (out of scope here).
35369
+ *
35370
+ * The whole-block `WindowsConfiguration` / `OntapConfiguration` /
35371
+ * `OpenZFSConfiguration` entries are gone as of the variant reverse-mappers
35372
+ * — only the individually-unreadable leaves above stay unknown.
35239
35373
  */
35240
35374
  getDriftUnknownPaths(resourceType) {
35241
35375
  if (resourceType !== "AWS::FSx::FileSystem") return [];
35242
35376
  return [
35243
35377
  "SecurityGroupIds",
35244
35378
  "BackupId",
35245
- "WindowsConfiguration",
35246
- "OntapConfiguration",
35247
- "OpenZFSConfiguration"
35379
+ "WindowsConfiguration.SelfManagedActiveDirectoryConfiguration.Password",
35380
+ "OntapConfiguration.FsxAdminPassword",
35381
+ "OpenZFSConfiguration.RootVolumeConfiguration"
35248
35382
  ];
35249
35383
  }
35250
35384
  /**
@@ -35252,7 +35386,11 @@ var FSxFileSystemProvider = class {
35252
35386
  * via `DescribeFileSystems`. Lustre data-repository fields (`ImportPath`
35253
35387
  * / `ExportPath` / `AutoImportPolicy` / `ImportedFileChunkSize`) are
35254
35388
  * mapped back from the nested `DataRepositoryConfiguration` the API
35255
- * returns. Returns `undefined` when the file system is gone.
35389
+ * returns. The Windows / ONTAP / OpenZFS variant blocks are reverse-mapped
35390
+ * by their respective `read*Configuration` helpers; the few inputs AWS
35391
+ * never returns stay listed in {@link getDriftUnknownPaths}. At most one
35392
+ * variant block is ever present (they key off `FileSystemType`).
35393
+ * Returns `undefined` when the file system is gone.
35256
35394
  */
35257
35395
  async readCurrentState(physicalId, _logicalId, resourceType) {
35258
35396
  if (resourceType !== "AWS::FSx::FileSystem") return void 0;
@@ -35265,47 +35403,59 @@ var FSxFileSystemProvider = class {
35265
35403
  }
35266
35404
  if (!fs) return void 0;
35267
35405
  const result = {};
35268
- if (fs.FileSystemType !== void 0) result["FileSystemType"] = fs.FileSystemType;
35269
- if (fs.StorageCapacity !== void 0) result["StorageCapacity"] = fs.StorageCapacity;
35270
- if (fs.StorageType !== void 0) result["StorageType"] = fs.StorageType;
35271
- if (fs.SubnetIds !== void 0) result["SubnetIds"] = [...fs.SubnetIds];
35272
- if (fs.KmsKeyId !== void 0) result["KmsKeyId"] = fs.KmsKeyId;
35273
- if (fs.FileSystemTypeVersion !== void 0) result["FileSystemTypeVersion"] = fs.FileSystemTypeVersion;
35274
- if (fs.NetworkType !== void 0) result["NetworkType"] = fs.NetworkType;
35406
+ putIfDefined(result, "FileSystemType", fs.FileSystemType);
35407
+ putIfDefined(result, "StorageCapacity", fs.StorageCapacity);
35408
+ putIfDefined(result, "StorageType", fs.StorageType);
35409
+ putIfDefined(result, "SubnetIds", fs.SubnetIds ? [...fs.SubnetIds] : void 0);
35410
+ putIfDefined(result, "KmsKeyId", fs.KmsKeyId);
35411
+ putIfDefined(result, "FileSystemTypeVersion", fs.FileSystemTypeVersion);
35412
+ putIfDefined(result, "NetworkType", fs.NetworkType);
35275
35413
  const lustre = fs.LustreConfiguration;
35276
35414
  if (lustre) {
35277
35415
  const config = {};
35278
- if (lustre.WeeklyMaintenanceStartTime !== void 0) config["WeeklyMaintenanceStartTime"] = lustre.WeeklyMaintenanceStartTime;
35279
- if (lustre.DeploymentType !== void 0) config["DeploymentType"] = lustre.DeploymentType;
35280
- if (lustre.PerUnitStorageThroughput !== void 0) config["PerUnitStorageThroughput"] = lustre.PerUnitStorageThroughput;
35281
- if (lustre.DailyAutomaticBackupStartTime !== void 0) config["DailyAutomaticBackupStartTime"] = lustre.DailyAutomaticBackupStartTime;
35282
- if (lustre.AutomaticBackupRetentionDays !== void 0) config["AutomaticBackupRetentionDays"] = lustre.AutomaticBackupRetentionDays;
35283
- if (lustre.CopyTagsToBackups !== void 0) config["CopyTagsToBackups"] = lustre.CopyTagsToBackups;
35284
- if (lustre.DriveCacheType !== void 0) config["DriveCacheType"] = lustre.DriveCacheType;
35285
- if (lustre.DataCompressionType !== void 0) config["DataCompressionType"] = lustre.DataCompressionType;
35286
- if (lustre.EfaEnabled !== void 0) config["EfaEnabled"] = lustre.EfaEnabled;
35287
- if (lustre.ThroughputCapacity !== void 0) config["ThroughputCapacity"] = lustre.ThroughputCapacity;
35416
+ putIfDefined(config, "WeeklyMaintenanceStartTime", lustre.WeeklyMaintenanceStartTime);
35417
+ putIfDefined(config, "DeploymentType", lustre.DeploymentType);
35418
+ putIfDefined(config, "PerUnitStorageThroughput", lustre.PerUnitStorageThroughput);
35419
+ putIfDefined(config, "DailyAutomaticBackupStartTime", lustre.DailyAutomaticBackupStartTime);
35420
+ putIfDefined(config, "AutomaticBackupRetentionDays", lustre.AutomaticBackupRetentionDays);
35421
+ putIfDefined(config, "CopyTagsToBackups", lustre.CopyTagsToBackups);
35422
+ putIfDefined(config, "DriveCacheType", lustre.DriveCacheType);
35423
+ putIfDefined(config, "DataCompressionType", lustre.DataCompressionType);
35424
+ putIfDefined(config, "EfaEnabled", lustre.EfaEnabled);
35425
+ putIfDefined(config, "ThroughputCapacity", lustre.ThroughputCapacity);
35288
35426
  if (lustre.MetadataConfiguration) {
35289
35427
  const metadata = {};
35290
- if (lustre.MetadataConfiguration.Mode !== void 0) metadata["Mode"] = lustre.MetadataConfiguration.Mode;
35291
- if (lustre.MetadataConfiguration.Iops !== void 0) metadata["Iops"] = lustre.MetadataConfiguration.Iops;
35428
+ putIfDefined(metadata, "Mode", lustre.MetadataConfiguration.Mode);
35429
+ putIfDefined(metadata, "Iops", lustre.MetadataConfiguration.Iops);
35292
35430
  if (Object.keys(metadata).length > 0) config["MetadataConfiguration"] = metadata;
35293
35431
  }
35294
35432
  if (lustre.DataReadCacheConfiguration) {
35295
35433
  const readCache = {};
35296
- if (lustre.DataReadCacheConfiguration.SizingMode !== void 0) readCache["SizingMode"] = lustre.DataReadCacheConfiguration.SizingMode;
35297
- if (lustre.DataReadCacheConfiguration.SizeGiB !== void 0) readCache["SizeGiB"] = lustre.DataReadCacheConfiguration.SizeGiB;
35434
+ putIfDefined(readCache, "SizingMode", lustre.DataReadCacheConfiguration.SizingMode);
35435
+ putIfDefined(readCache, "SizeGiB", lustre.DataReadCacheConfiguration.SizeGiB);
35298
35436
  if (Object.keys(readCache).length > 0) config["DataReadCacheConfiguration"] = readCache;
35299
35437
  }
35300
35438
  const dataRepo = lustre.DataRepositoryConfiguration;
35301
35439
  if (dataRepo) {
35302
- if (dataRepo.ImportPath !== void 0) config["ImportPath"] = dataRepo.ImportPath;
35303
- if (dataRepo.ExportPath !== void 0) config["ExportPath"] = dataRepo.ExportPath;
35304
- if (dataRepo.AutoImportPolicy !== void 0) config["AutoImportPolicy"] = dataRepo.AutoImportPolicy;
35305
- if (dataRepo.ImportedFileChunkSize !== void 0) config["ImportedFileChunkSize"] = dataRepo.ImportedFileChunkSize;
35440
+ putIfDefined(config, "ImportPath", dataRepo.ImportPath);
35441
+ putIfDefined(config, "ExportPath", dataRepo.ExportPath);
35442
+ putIfDefined(config, "AutoImportPolicy", dataRepo.AutoImportPolicy);
35443
+ putIfDefined(config, "ImportedFileChunkSize", dataRepo.ImportedFileChunkSize);
35306
35444
  }
35307
35445
  if (Object.keys(config).length > 0) result["LustreConfiguration"] = config;
35308
35446
  }
35447
+ if (fs.WindowsConfiguration) {
35448
+ const config = this.readWindowsConfiguration(fs.WindowsConfiguration);
35449
+ if (Object.keys(config).length > 0) result["WindowsConfiguration"] = config;
35450
+ }
35451
+ if (fs.OntapConfiguration) {
35452
+ const config = this.readOntapConfiguration(fs.OntapConfiguration);
35453
+ if (Object.keys(config).length > 0) result["OntapConfiguration"] = config;
35454
+ }
35455
+ if (fs.OpenZFSConfiguration) {
35456
+ const config = this.readOpenZFSConfiguration(fs.OpenZFSConfiguration);
35457
+ if (Object.keys(config).length > 0) result["OpenZFSConfiguration"] = config;
35458
+ }
35309
35459
  result["Tags"] = normalizeAwsTagsToCfn(fs.Tags);
35310
35460
  return result;
35311
35461
  }
@@ -35353,8 +35503,8 @@ var FSxFileSystemProvider = class {
35353
35503
  * FSx providers' 1-hour ceiling so the slowest realistic create/terminate
35354
35504
  * still fits inside the per-resource deadline.
35355
35505
  */
35356
- const DEFAULT_MAX_WAIT_MS = 3600 * 1e3;
35357
- const DEFAULT_POLL_INTERVAL_MS = 15e3;
35506
+ const DEFAULT_MAX_WAIT_MS$2 = 3600 * 1e3;
35507
+ const DEFAULT_POLL_INTERVAL_MS$2 = 15e3;
35358
35508
  /** Cluster states that mean "create succeeded, the cluster is up". */
35359
35509
  const CREATE_READY_STATES = /* @__PURE__ */ new Set(["WAITING", "RUNNING"]);
35360
35510
  /**
@@ -35388,7 +35538,7 @@ const MUTABLE_TOP_LEVEL_PROPS = /* @__PURE__ */ new Set([
35388
35538
  "ManagedScalingPolicy",
35389
35539
  "AutoTerminationPolicy"
35390
35540
  ]);
35391
- const toNumber = (v) => {
35541
+ const toNumber$2 = (v) => {
35392
35542
  if (v === void 0) return void 0;
35393
35543
  const n = Number(v);
35394
35544
  return Number.isNaN(n) ? void 0 : n;
@@ -35398,7 +35548,7 @@ const toBoolean = (v) => {
35398
35548
  if (typeof v === "string") return v === "true";
35399
35549
  return Boolean(v);
35400
35550
  };
35401
- const jsonEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
35551
+ const jsonEqual$2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
35402
35552
  /**
35403
35553
  * SDK Provider for `AWS::EMR::Cluster` (EMR on EC2).
35404
35554
  *
@@ -35444,8 +35594,8 @@ var EMRClusterProvider = class {
35444
35594
  pollIntervalMs;
35445
35595
  maxWaitMs;
35446
35596
  constructor(options) {
35447
- this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
35448
- this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS;
35597
+ this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS$2;
35598
+ this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS$2;
35449
35599
  }
35450
35600
  handledProperties = /* @__PURE__ */ new Map([["AWS::EMR::Cluster", /* @__PURE__ */ new Set([
35451
35601
  "AdditionalInfo",
@@ -35517,10 +35667,10 @@ var EMRClusterProvider = class {
35517
35667
  CustomAmiId: properties["CustomAmiId"],
35518
35668
  OSReleaseLabel: properties["OSReleaseLabel"],
35519
35669
  SecurityConfiguration: properties["SecurityConfiguration"],
35520
- EbsRootVolumeSize: toNumber(properties["EbsRootVolumeSize"]),
35521
- EbsRootVolumeIops: toNumber(properties["EbsRootVolumeIops"]),
35522
- EbsRootVolumeThroughput: toNumber(properties["EbsRootVolumeThroughput"]),
35523
- StepConcurrencyLevel: toNumber(properties["StepConcurrencyLevel"]),
35670
+ EbsRootVolumeSize: toNumber$2(properties["EbsRootVolumeSize"]),
35671
+ EbsRootVolumeIops: toNumber$2(properties["EbsRootVolumeIops"]),
35672
+ EbsRootVolumeThroughput: toNumber$2(properties["EbsRootVolumeThroughput"]),
35673
+ StepConcurrencyLevel: toNumber$2(properties["StepConcurrencyLevel"]),
35524
35674
  VisibleToAllUsers: toBoolean(properties["VisibleToAllUsers"]),
35525
35675
  Applications: properties["Applications"],
35526
35676
  Configurations: properties["Configurations"],
@@ -35609,7 +35759,7 @@ var EMRClusterProvider = class {
35609
35759
  return {
35610
35760
  InstanceRole: role,
35611
35761
  InstanceType: raw["InstanceType"],
35612
- InstanceCount: toNumber(raw["InstanceCount"]),
35762
+ InstanceCount: toNumber$2(raw["InstanceCount"]),
35613
35763
  Name: raw["Name"],
35614
35764
  Market: raw["Market"],
35615
35765
  BidPrice: raw["BidPrice"],
@@ -35623,8 +35773,8 @@ var EMRClusterProvider = class {
35623
35773
  return {
35624
35774
  InstanceFleetType: type,
35625
35775
  Name: raw["Name"],
35626
- TargetOnDemandCapacity: toNumber(raw["TargetOnDemandCapacity"]),
35627
- TargetSpotCapacity: toNumber(raw["TargetSpotCapacity"]),
35776
+ TargetOnDemandCapacity: toNumber$2(raw["TargetOnDemandCapacity"]),
35777
+ TargetSpotCapacity: toNumber$2(raw["TargetSpotCapacity"]),
35628
35778
  InstanceTypeConfigs: raw["InstanceTypeConfigs"],
35629
35779
  LaunchSpecifications: raw["LaunchSpecifications"],
35630
35780
  ResizeSpecifications: raw["ResizeSpecifications"]
@@ -35637,28 +35787,28 @@ var EMRClusterProvider = class {
35637
35787
  return {
35638
35788
  ComputeLimits: {
35639
35789
  UnitType: limits["UnitType"],
35640
- MinimumCapacityUnits: toNumber(limits["MinimumCapacityUnits"]),
35641
- MaximumCapacityUnits: toNumber(limits["MaximumCapacityUnits"]),
35642
- MaximumOnDemandCapacityUnits: toNumber(limits["MaximumOnDemandCapacityUnits"]),
35643
- MaximumCoreCapacityUnits: toNumber(limits["MaximumCoreCapacityUnits"])
35790
+ MinimumCapacityUnits: toNumber$2(limits["MinimumCapacityUnits"]),
35791
+ MaximumCapacityUnits: toNumber$2(limits["MaximumCapacityUnits"]),
35792
+ MaximumOnDemandCapacityUnits: toNumber$2(limits["MaximumOnDemandCapacityUnits"]),
35793
+ MaximumCoreCapacityUnits: toNumber$2(limits["MaximumCoreCapacityUnits"])
35644
35794
  },
35645
- UtilizationPerformanceIndex: toNumber(config["UtilizationPerformanceIndex"]),
35795
+ UtilizationPerformanceIndex: toNumber$2(config["UtilizationPerformanceIndex"]),
35646
35796
  ScalingStrategy: config["ScalingStrategy"]
35647
35797
  };
35648
35798
  }
35649
35799
  toAutoTerminationPolicy(config) {
35650
35800
  if (!config) return void 0;
35651
- return { IdleTimeout: toNumber(config["IdleTimeout"]) };
35801
+ return { IdleTimeout: toNumber$2(config["IdleTimeout"]) };
35652
35802
  }
35653
35803
  async update(logicalId, physicalId, resourceType, properties, previousProperties) {
35654
- const changed = (key) => !jsonEqual(properties[key], previousProperties[key]);
35804
+ const changed = (key) => !jsonEqual$2(properties[key], previousProperties[key]);
35655
35805
  const nextInstances = properties["Instances"] ?? {};
35656
35806
  const prevInstances = previousProperties["Instances"] ?? {};
35657
35807
  let terminationProtectedChanged = false;
35658
35808
  if (changed("Instances")) {
35659
35809
  const instanceKeys = /* @__PURE__ */ new Set([...Object.keys(nextInstances), ...Object.keys(prevInstances)]);
35660
35810
  for (const key of instanceKeys) {
35661
- if (jsonEqual(nextInstances[key], prevInstances[key])) continue;
35811
+ if (jsonEqual$2(nextInstances[key], prevInstances[key])) continue;
35662
35812
  if (key === "TerminationProtected") {
35663
35813
  terminationProtectedChanged = true;
35664
35814
  continue;
@@ -35698,7 +35848,7 @@ var EMRClusterProvider = class {
35698
35848
  }));
35699
35849
  if (stepConcurrencyChanged) await this.getClient().send(new ModifyClusterCommand({
35700
35850
  ClusterId: physicalId,
35701
- StepConcurrencyLevel: toNumber(properties["StepConcurrencyLevel"])
35851
+ StepConcurrencyLevel: toNumber$2(properties["StepConcurrencyLevel"])
35702
35852
  }));
35703
35853
  if (managedScalingChanged) {
35704
35854
  const next = this.toManagedScalingPolicy(properties["ManagedScalingPolicy"]);
@@ -36150,6 +36300,570 @@ var EMRClusterProvider = class {
36150
36300
  }
36151
36301
  };
36152
36302
 
36303
+ //#endregion
36304
+ //#region src/provisioning/providers/emr-instance-group-config-provider.ts
36305
+ /**
36306
+ * Default polling budget for an instance group reaching RUNNING. Adding a
36307
+ * group to an already-WAITING cluster provisions + bootstraps its EC2
36308
+ * instances (typically 2-6 minutes); a resize settles faster. Reuse the
36309
+ * EMR Cluster provider's 1-hour ceiling so the slowest realistic add still
36310
+ * fits inside the per-resource deadline.
36311
+ */
36312
+ const DEFAULT_MAX_WAIT_MS$1 = 3600 * 1e3;
36313
+ const DEFAULT_POLL_INTERVAL_MS$1 = 15e3;
36314
+ /** Instance-group state that means "the group is up and idle/serving". */
36315
+ const READY_STATES$1 = /* @__PURE__ */ new Set(["RUNNING"]);
36316
+ /**
36317
+ * Instance-group states that mean "the group is gone / failed" — a hard
36318
+ * error during a create/resize wait (an ARRESTED group failed to provision;
36319
+ * TERMINATED/ENDED mean it will never reach RUNNING).
36320
+ */
36321
+ const FAILED_STATES$1 = /* @__PURE__ */ new Set([
36322
+ "ARRESTED",
36323
+ "TERMINATED",
36324
+ "ENDED"
36325
+ ]);
36326
+ const toNumber$1 = (v) => {
36327
+ if (v === void 0) return void 0;
36328
+ const n = Number(v);
36329
+ return Number.isNaN(n) ? void 0 : n;
36330
+ };
36331
+ const jsonEqual$1 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
36332
+ /**
36333
+ * SDK Provider for `AWS::EMR::InstanceGroupConfig` (issue #1070).
36334
+ *
36335
+ * This type adds a standalone instance group (MASTER / CORE / TASK) to an
36336
+ * EXISTING EMR cluster (referenced by `JobFlowId`), rather than declaring the
36337
+ * group inline in `AWS::EMR::Cluster.Instances`. It is
36338
+ * `ProvisioningType: NON_PROVISIONABLE` in the CFn registry, so Cloud Control
36339
+ * cannot handle it — pre-flight would otherwise reject it via
36340
+ * `unsupported-types.generated.ts`.
36341
+ *
36342
+ * Lifecycle:
36343
+ * - `create` → `AddInstanceGroups` (one group per call) + poll
36344
+ * `ListInstanceGroups` until the new group is `RUNNING`. A failed terminal
36345
+ * (`ARRESTED` / `TERMINATED` / `ENDED`) during the wait is a hard error.
36346
+ * - `update` → only the two AWS-mutable properties: `InstanceCount`
36347
+ * (`ModifyInstanceGroups`, resize; polled until settled) and
36348
+ * `AutoScalingPolicy` (`PutAutoScalingPolicy` / `RemoveAutoScalingPolicy`).
36349
+ * Every other property is registry-createOnly → routed through
36350
+ * DELETE+CREATE by the replacement-detection layer; a createOnly change
36351
+ * that reaches `update()` anyway is refused with a `--replace` pointer.
36352
+ * - `delete` → **no standalone AWS API exists.** EMR cannot remove an
36353
+ * instance group from a running cluster; a group's only lifecycle end is
36354
+ * cluster termination. In the normal `cdkd destroy` the parent
36355
+ * `AWS::EMR::Cluster` is terminated in the same run (its `TerminateJobFlows`
36356
+ * releases every group + its EC2 instances), so this delete is a no-op that
36357
+ * just drops cdkd state — leaving ZERO orphans. As a best effort for the
36358
+ * less common "delete only the group, keep the cluster" case, a TASK group
36359
+ * is scaled to 0 instances (`ModifyInstanceGroups InstanceCount: 0`) to
36360
+ * release its instances; MASTER/CORE groups cannot be scaled to 0 and are a
36361
+ * pure no-op. Never blocks the destroy (warn-and-continue).
36362
+ *
36363
+ * `getMinResourceTimeoutMs()` lifts the deploy engine's per-resource deadline
36364
+ * to the polling ceiling (mirrors `EMRClusterProvider`) so a slow add/resize
36365
+ * does not require `--resource-timeout`.
36366
+ */
36367
+ var EMRInstanceGroupConfigProvider = class {
36368
+ /**
36369
+ * Cloud Control has NO handlers for this type
36370
+ * (`ProvisioningType: NON_PROVISIONABLE`), so the deploy engine's #614
36371
+ * silent-drop auto-route MUST NOT send an unhandled-property template to CC
36372
+ * — it would fail at provisioning time with an opaque
36373
+ * UnsupportedActionException. With this opt-out the ProviderRegistry rejects
36374
+ * such templates pre-flight with a clear error instead.
36375
+ */
36376
+ disableCcApiFallback = true;
36377
+ client;
36378
+ providerRegion = process.env["AWS_REGION"];
36379
+ logger = getLogger().child("EMRInstanceGroupConfigProvider");
36380
+ pollIntervalMs;
36381
+ maxWaitMs;
36382
+ constructor(options) {
36383
+ this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS$1;
36384
+ this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS$1;
36385
+ }
36386
+ handledProperties = /* @__PURE__ */ new Map([["AWS::EMR::InstanceGroupConfig", /* @__PURE__ */ new Set([
36387
+ "AutoScalingPolicy",
36388
+ "BidPrice",
36389
+ "Configurations",
36390
+ "CustomAmiId",
36391
+ "EbsConfiguration",
36392
+ "InstanceCount",
36393
+ "InstanceRole",
36394
+ "InstanceType",
36395
+ "JobFlowId",
36396
+ "Market",
36397
+ "Name"
36398
+ ])]]);
36399
+ getClient() {
36400
+ if (!this.client) this.client = new EMRClient(this.providerRegion ? { region: this.providerRegion } : {});
36401
+ return this.client;
36402
+ }
36403
+ getMinResourceTimeoutMs() {
36404
+ return this.maxWaitMs + this.pollIntervalMs;
36405
+ }
36406
+ async create(logicalId, resourceType, properties) {
36407
+ if (resourceType !== "AWS::EMR::InstanceGroupConfig") throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
36408
+ const jobFlowId = properties["JobFlowId"];
36409
+ if (!jobFlowId) throw new ProvisioningError(`EMR InstanceGroupConfig ${logicalId} is missing JobFlowId (the parent cluster id)`, resourceType, logicalId);
36410
+ this.logger.debug(`Adding EMR instance group ${logicalId} to cluster ${jobFlowId}`);
36411
+ try {
36412
+ const group = this.toInstanceGroupConfig(properties);
36413
+ const groupId = (await this.getClient().send(new AddInstanceGroupsCommand({
36414
+ JobFlowId: jobFlowId,
36415
+ InstanceGroups: [group]
36416
+ }))).InstanceGroupIds?.[0];
36417
+ if (!groupId) throw new ProvisioningError(`EMR AddInstanceGroups for ${logicalId} returned no instance group id`, resourceType, logicalId);
36418
+ await this.waitForGroupReady(jobFlowId, groupId, logicalId, resourceType, toNumber$1(properties["InstanceCount"]) ?? 0);
36419
+ this.logger.debug(`Successfully added EMR instance group ${logicalId}: ${groupId}`);
36420
+ return {
36421
+ physicalId: groupId,
36422
+ attributes: { Id: groupId }
36423
+ };
36424
+ } catch (error) {
36425
+ if (error instanceof ProvisioningError) throw error;
36426
+ const cause = error instanceof Error ? error : void 0;
36427
+ throw new ProvisioningError(`Failed to add EMR instance group ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
36428
+ }
36429
+ }
36430
+ toInstanceGroupConfig(properties) {
36431
+ return {
36432
+ InstanceRole: properties["InstanceRole"],
36433
+ InstanceType: properties["InstanceType"],
36434
+ InstanceCount: toNumber$1(properties["InstanceCount"]),
36435
+ Name: properties["Name"],
36436
+ Market: properties["Market"],
36437
+ BidPrice: properties["BidPrice"],
36438
+ Configurations: properties["Configurations"],
36439
+ EbsConfiguration: properties["EbsConfiguration"],
36440
+ AutoScalingPolicy: properties["AutoScalingPolicy"],
36441
+ CustomAmiId: properties["CustomAmiId"]
36442
+ };
36443
+ }
36444
+ async update(logicalId, physicalId, resourceType, properties, previousProperties) {
36445
+ const changed = (key) => !jsonEqual$1(properties[key], previousProperties[key]);
36446
+ const MUTABLE = /* @__PURE__ */ new Set(["InstanceCount", "AutoScalingPolicy"]);
36447
+ for (const key of Object.keys({
36448
+ ...properties,
36449
+ ...previousProperties
36450
+ })) {
36451
+ if (!changed(key)) continue;
36452
+ if (!MUTABLE.has(key)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS EMR InstanceGroupConfig ${key} is immutable on AWS — it is fixed when the instance group is created. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
36453
+ }
36454
+ const instanceCountChanged = changed("InstanceCount");
36455
+ const autoScalingChanged = changed("AutoScalingPolicy");
36456
+ if (!instanceCountChanged && !autoScalingChanged) {
36457
+ this.logger.debug(`No mutable diff for EMR instance group ${logicalId}, skipping update`);
36458
+ return {
36459
+ physicalId,
36460
+ wasReplaced: false
36461
+ };
36462
+ }
36463
+ const jobFlowId = properties["JobFlowId"];
36464
+ this.logger.debug(`Updating EMR instance group ${logicalId}: ${physicalId}`);
36465
+ try {
36466
+ if (instanceCountChanged) {
36467
+ await this.getClient().send(new ModifyInstanceGroupsCommand({
36468
+ ...jobFlowId && { ClusterId: jobFlowId },
36469
+ InstanceGroups: [{
36470
+ InstanceGroupId: physicalId,
36471
+ InstanceCount: toNumber$1(properties["InstanceCount"])
36472
+ }]
36473
+ }));
36474
+ if (jobFlowId) await this.waitForGroupReady(jobFlowId, physicalId, logicalId, resourceType, toNumber$1(properties["InstanceCount"]) ?? 0);
36475
+ }
36476
+ if (autoScalingChanged) {
36477
+ if (!jobFlowId) throw new ProvisioningError(`EMR InstanceGroupConfig ${logicalId} AutoScalingPolicy update needs JobFlowId (the cluster id), which is absent`, resourceType, logicalId, physicalId);
36478
+ const policy = properties["AutoScalingPolicy"];
36479
+ if (policy) await this.getClient().send(new PutAutoScalingPolicyCommand({
36480
+ ClusterId: jobFlowId,
36481
+ InstanceGroupId: physicalId,
36482
+ AutoScalingPolicy: policy
36483
+ }));
36484
+ else await this.getClient().send(new RemoveAutoScalingPolicyCommand({
36485
+ ClusterId: jobFlowId,
36486
+ InstanceGroupId: physicalId
36487
+ }));
36488
+ }
36489
+ this.logger.debug(`Successfully updated EMR instance group ${logicalId}`);
36490
+ return {
36491
+ physicalId,
36492
+ wasReplaced: false,
36493
+ attributes: { Id: physicalId }
36494
+ };
36495
+ } catch (error) {
36496
+ if (error instanceof ProvisioningError || error instanceof ResourceUpdateNotSupportedError) throw error;
36497
+ const cause = error instanceof Error ? error : void 0;
36498
+ throw new ProvisioningError(`Failed to update EMR instance group ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
36499
+ }
36500
+ }
36501
+ async delete(logicalId, physicalId, resourceType, properties, context) {
36502
+ const role = properties?.["InstanceRole"];
36503
+ const jobFlowId = properties?.["JobFlowId"];
36504
+ if (role === "TASK" && jobFlowId) {
36505
+ try {
36506
+ await this.getClient().send(new ModifyInstanceGroupsCommand({
36507
+ ClusterId: jobFlowId,
36508
+ InstanceGroups: [{
36509
+ InstanceGroupId: physicalId,
36510
+ InstanceCount: 0
36511
+ }]
36512
+ }));
36513
+ this.logger.debug(`Scaled EMR TASK instance group ${physicalId} to 0 to release its instances (no standalone delete API exists)`);
36514
+ } catch (error) {
36515
+ if (error instanceof InvalidRequestException) {
36516
+ assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
36517
+ this.logger.debug(`EMR instance group ${physicalId} scale-to-0 skipped (cluster/group gone): ${error.message}`);
36518
+ } else this.logger.warn(`Best-effort scale-to-0 of EMR instance group ${physicalId} failed: ${error instanceof Error ? error.message : String(error)} — its instances are released when the parent cluster terminates`);
36519
+ }
36520
+ return;
36521
+ }
36522
+ this.logger.debug(`EMR instance group ${physicalId} (role ${role ?? "unknown"}) has no standalone delete API; its instances are released when the parent cluster terminates. Removing cdkd state only.`);
36523
+ }
36524
+ async getAttribute(physicalId, _resourceType, attributeName) {
36525
+ if (attributeName === "Id") return physicalId;
36526
+ }
36527
+ /**
36528
+ * Poll until the group is `RUNNING` AND its `RunningInstanceCount` equals
36529
+ * `expectedCount`. The count check is load-bearing on a resize: right after
36530
+ * `ModifyInstanceGroups` the group is still in the PRE-resize `RUNNING`
36531
+ * state (EMR has not flipped it to `RESIZING` yet), so a State-only wait
36532
+ * would return before the resize even starts. Waiting on the running count
36533
+ * reaching the requested target settles both create (0 -> N provisioning)
36534
+ * and resize (M -> N add/remove) correctly.
36535
+ */
36536
+ async waitForGroupReady(clusterId, groupId, logicalId, resourceType, expectedCount) {
36537
+ const startTime = Date.now();
36538
+ const transientState = { count: 0 };
36539
+ while (Date.now() - startTime < this.maxWaitMs) {
36540
+ const group = await this.findGroupForPoll(clusterId, groupId, transientState);
36541
+ const state = group?.Status?.State;
36542
+ if (state && READY_STATES$1.has(state) && group?.RunningInstanceCount === expectedCount) return;
36543
+ if (state && FAILED_STATES$1.has(state)) throw new ProvisioningError(`EMR instance group ${groupId} entered failed state ${state}: ${group?.Status?.StateChangeReason?.Message ?? "no state-change reason reported"}`, resourceType, logicalId, groupId);
36544
+ this.logger.debug(`EMR instance group ${groupId} state: ${state ?? "unknown"}, running ${group?.RunningInstanceCount ?? "?"}/${expectedCount}, waiting...`);
36545
+ await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
36546
+ }
36547
+ throw new ProvisioningError(`Timed out waiting for EMR instance group ${groupId} to reach RUNNING with ${expectedCount} instance(s) (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, groupId);
36548
+ }
36549
+ /**
36550
+ * `ListInstanceGroups` (paginated) for the cluster, returning the single
36551
+ * group whose `Id` matches. Absorbs up to `maxConsecutiveTransient`
36552
+ * consecutive transient errors (throttle / 5xx / reset) so a single blip
36553
+ * during a 10-minute poll does not spuriously fail the create.
36554
+ */
36555
+ async findGroupForPoll(clusterId, groupId, transientState, maxConsecutiveTransient = 5) {
36556
+ try {
36557
+ let marker;
36558
+ do {
36559
+ const resp = await this.getClient().send(new ListInstanceGroupsCommand({
36560
+ ClusterId: clusterId,
36561
+ ...marker && { Marker: marker }
36562
+ }));
36563
+ const found = (resp.InstanceGroups ?? []).find((g) => g.Id === groupId);
36564
+ if (found) {
36565
+ transientState.count = 0;
36566
+ return found;
36567
+ }
36568
+ marker = resp.Marker;
36569
+ } while (marker);
36570
+ transientState.count = 0;
36571
+ return;
36572
+ } catch (error) {
36573
+ const name = error instanceof Error ? error.name : "";
36574
+ const msg = error instanceof Error ? error.message : String(error);
36575
+ if ((name === "ThrottlingException" || name === "InternalServerException" || name === "InternalServerError" || name === "TimeoutError" || /rate exceeded|too many requests|throttl|timed? ?out|ECONNRESET|EPIPE|socket hang up/i.test(msg)) && transientState.count < maxConsecutiveTransient) {
36576
+ transientState.count += 1;
36577
+ this.logger.debug(`Transient ListInstanceGroups error while polling ${groupId} (${transientState.count}/${maxConsecutiveTransient}): ${msg} — retrying`);
36578
+ return;
36579
+ }
36580
+ throw error;
36581
+ }
36582
+ }
36583
+ };
36584
+
36585
+ //#endregion
36586
+ //#region src/provisioning/providers/emr-instance-fleet-config-provider.ts
36587
+ /**
36588
+ * Default polling budget for an instance fleet reaching RUNNING. Adding a
36589
+ * fleet to an already-WAITING cluster provisions + bootstraps its EC2
36590
+ * instances (typically 2-6 minutes); a resize settles faster. Reuse the
36591
+ * EMR Cluster provider's 1-hour ceiling so the slowest realistic add still
36592
+ * fits inside the per-resource deadline.
36593
+ */
36594
+ const DEFAULT_MAX_WAIT_MS = 3600 * 1e3;
36595
+ const DEFAULT_POLL_INTERVAL_MS = 15e3;
36596
+ /** Instance-fleet state that means "the fleet is up and idle/serving". */
36597
+ const READY_STATES = /* @__PURE__ */ new Set(["RUNNING"]);
36598
+ /**
36599
+ * Instance-fleet states that mean "the fleet is gone" — a hard error during a
36600
+ * create/resize wait (it will never reach RUNNING).
36601
+ */
36602
+ const FAILED_STATES = /* @__PURE__ */ new Set(["TERMINATED"]);
36603
+ const toNumber = (v) => {
36604
+ if (v === void 0) return void 0;
36605
+ const n = Number(v);
36606
+ return Number.isNaN(n) ? void 0 : n;
36607
+ };
36608
+ const jsonEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
36609
+ /**
36610
+ * SDK Provider for `AWS::EMR::InstanceFleetConfig` (issue #1070).
36611
+ *
36612
+ * This type adds a standalone instance fleet (MASTER / CORE / TASK) to an
36613
+ * EXISTING EMR cluster (referenced by `ClusterId`), rather than declaring the
36614
+ * fleet inline in `AWS::EMR::Cluster.Instances`. It is
36615
+ * `ProvisioningType: NON_PROVISIONABLE` in the CFn registry, so Cloud Control
36616
+ * cannot handle it — pre-flight would otherwise reject it via
36617
+ * `unsupported-types.generated.ts`.
36618
+ *
36619
+ * Lifecycle:
36620
+ * - `create` → `AddInstanceFleet` + poll `ListInstanceFleets` until the new
36621
+ * fleet is `RUNNING`. A `TERMINATED` terminal during the wait is a hard
36622
+ * error.
36623
+ * - `update` → only the AWS-mutable properties: `TargetOnDemandCapacity`,
36624
+ * `TargetSpotCapacity`, `ResizeSpecifications`, and `InstanceTypeConfigs`
36625
+ * (all via `ModifyInstanceFleet`; the resize is polled until settled).
36626
+ * `Name` / `LaunchSpecifications` / `InstanceFleetType` are
36627
+ * registry-createOnly → routed through DELETE+CREATE by the
36628
+ * replacement-detection layer; a createOnly change that reaches `update()`
36629
+ * anyway is refused with a `--replace` pointer.
36630
+ * - `delete` → **no standalone AWS API exists.** EMR cannot remove an
36631
+ * instance fleet from a running cluster; a fleet's only lifecycle end is
36632
+ * cluster termination. In the normal `cdkd destroy` the parent
36633
+ * `AWS::EMR::Cluster` is terminated in the same run (its `TerminateJobFlows`
36634
+ * releases every fleet + its EC2 instances), so this delete is a no-op that
36635
+ * just drops cdkd state — leaving ZERO orphans. As a best effort for the
36636
+ * less common "delete only the fleet, keep the cluster" case, a TASK fleet
36637
+ * is scaled to 0 target capacity (`ModifyInstanceFleet`) to release its
36638
+ * instances; MASTER/CORE fleets cannot be scaled to 0 and are a pure no-op.
36639
+ * Never blocks the destroy (warn-and-continue).
36640
+ *
36641
+ * `getMinResourceTimeoutMs()` lifts the deploy engine's per-resource deadline
36642
+ * to the polling ceiling (mirrors `EMRClusterProvider`) so a slow add/resize
36643
+ * does not require `--resource-timeout`.
36644
+ */
36645
+ var EMRInstanceFleetConfigProvider = class {
36646
+ /**
36647
+ * Cloud Control has NO handlers for this type
36648
+ * (`ProvisioningType: NON_PROVISIONABLE`), so the deploy engine's #614
36649
+ * silent-drop auto-route MUST NOT send an unhandled-property template to CC
36650
+ * — it would fail at provisioning time with an opaque
36651
+ * UnsupportedActionException. With this opt-out the ProviderRegistry rejects
36652
+ * such templates pre-flight with a clear error instead.
36653
+ */
36654
+ disableCcApiFallback = true;
36655
+ client;
36656
+ providerRegion = process.env["AWS_REGION"];
36657
+ logger = getLogger().child("EMRInstanceFleetConfigProvider");
36658
+ pollIntervalMs;
36659
+ maxWaitMs;
36660
+ constructor(options) {
36661
+ this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
36662
+ this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS;
36663
+ }
36664
+ handledProperties = /* @__PURE__ */ new Map([["AWS::EMR::InstanceFleetConfig", /* @__PURE__ */ new Set([
36665
+ "ClusterId",
36666
+ "InstanceFleetType",
36667
+ "InstanceTypeConfigs",
36668
+ "LaunchSpecifications",
36669
+ "Name",
36670
+ "ResizeSpecifications",
36671
+ "TargetOnDemandCapacity",
36672
+ "TargetSpotCapacity"
36673
+ ])]]);
36674
+ getClient() {
36675
+ if (!this.client) this.client = new EMRClient(this.providerRegion ? { region: this.providerRegion } : {});
36676
+ return this.client;
36677
+ }
36678
+ getMinResourceTimeoutMs() {
36679
+ return this.maxWaitMs + this.pollIntervalMs;
36680
+ }
36681
+ async create(logicalId, resourceType, properties) {
36682
+ if (resourceType !== "AWS::EMR::InstanceFleetConfig") throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
36683
+ const clusterId = properties["ClusterId"];
36684
+ if (!clusterId) throw new ProvisioningError(`EMR InstanceFleetConfig ${logicalId} is missing ClusterId (the parent cluster id)`, resourceType, logicalId);
36685
+ this.logger.debug(`Adding EMR instance fleet ${logicalId} to cluster ${clusterId}`);
36686
+ try {
36687
+ const fleet = this.toInstanceFleetConfig(properties);
36688
+ const fleetId = (await this.getClient().send(new AddInstanceFleetCommand({
36689
+ ClusterId: clusterId,
36690
+ InstanceFleet: fleet
36691
+ }))).InstanceFleetId;
36692
+ if (!fleetId) throw new ProvisioningError(`EMR AddInstanceFleet for ${logicalId} returned no instance fleet id`, resourceType, logicalId);
36693
+ await this.waitForFleetReady(clusterId, fleetId, logicalId, resourceType, this.targetCapacity(properties), true);
36694
+ this.logger.debug(`Successfully added EMR instance fleet ${logicalId}: ${fleetId}`);
36695
+ return {
36696
+ physicalId: fleetId,
36697
+ attributes: { Id: fleetId }
36698
+ };
36699
+ } catch (error) {
36700
+ if (error instanceof ProvisioningError) throw error;
36701
+ const cause = error instanceof Error ? error : void 0;
36702
+ throw new ProvisioningError(`Failed to add EMR instance fleet ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
36703
+ }
36704
+ }
36705
+ toInstanceFleetConfig(properties) {
36706
+ return {
36707
+ InstanceFleetType: properties["InstanceFleetType"],
36708
+ Name: properties["Name"],
36709
+ TargetOnDemandCapacity: toNumber(properties["TargetOnDemandCapacity"]),
36710
+ TargetSpotCapacity: toNumber(properties["TargetSpotCapacity"]),
36711
+ InstanceTypeConfigs: properties["InstanceTypeConfigs"],
36712
+ LaunchSpecifications: properties["LaunchSpecifications"],
36713
+ ResizeSpecifications: properties["ResizeSpecifications"]
36714
+ };
36715
+ }
36716
+ async update(logicalId, physicalId, resourceType, properties, previousProperties) {
36717
+ const changed = (key) => !jsonEqual(properties[key], previousProperties[key]);
36718
+ const MUTABLE = /* @__PURE__ */ new Set([
36719
+ "TargetOnDemandCapacity",
36720
+ "TargetSpotCapacity",
36721
+ "ResizeSpecifications",
36722
+ "InstanceTypeConfigs"
36723
+ ]);
36724
+ for (const key of Object.keys({
36725
+ ...properties,
36726
+ ...previousProperties
36727
+ })) {
36728
+ if (!changed(key)) continue;
36729
+ if (!MUTABLE.has(key)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS EMR InstanceFleetConfig ${key} is immutable on AWS — it is fixed when the instance fleet is created. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
36730
+ }
36731
+ if (![...MUTABLE].some((k) => changed(k))) {
36732
+ this.logger.debug(`No mutable diff for EMR instance fleet ${logicalId}, skipping update`);
36733
+ return {
36734
+ physicalId,
36735
+ wasReplaced: false
36736
+ };
36737
+ }
36738
+ const clusterId = properties["ClusterId"];
36739
+ if (!clusterId) throw new ProvisioningError(`EMR InstanceFleetConfig ${logicalId} update needs ClusterId (the cluster id), which is absent`, resourceType, logicalId, physicalId);
36740
+ this.logger.debug(`Updating EMR instance fleet ${logicalId}: ${physicalId}`);
36741
+ try {
36742
+ const modify = {
36743
+ InstanceFleetId: physicalId,
36744
+ TargetOnDemandCapacity: toNumber(properties["TargetOnDemandCapacity"]),
36745
+ TargetSpotCapacity: toNumber(properties["TargetSpotCapacity"]),
36746
+ ResizeSpecifications: properties["ResizeSpecifications"],
36747
+ InstanceTypeConfigs: properties["InstanceTypeConfigs"]
36748
+ };
36749
+ await this.getClient().send(new ModifyInstanceFleetCommand({
36750
+ ClusterId: clusterId,
36751
+ InstanceFleet: modify
36752
+ }));
36753
+ const newTarget = this.targetCapacity(properties);
36754
+ const prevTarget = this.targetCapacity(previousProperties);
36755
+ await this.waitForFleetReady(clusterId, physicalId, logicalId, resourceType, newTarget, newTarget >= prevTarget);
36756
+ this.logger.debug(`Successfully updated EMR instance fleet ${logicalId}`);
36757
+ return {
36758
+ physicalId,
36759
+ wasReplaced: false,
36760
+ attributes: { Id: physicalId }
36761
+ };
36762
+ } catch (error) {
36763
+ if (error instanceof ProvisioningError || error instanceof ResourceUpdateNotSupportedError) throw error;
36764
+ const cause = error instanceof Error ? error : void 0;
36765
+ throw new ProvisioningError(`Failed to update EMR instance fleet ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
36766
+ }
36767
+ }
36768
+ async delete(logicalId, physicalId, resourceType, properties, context) {
36769
+ const fleetType = properties?.["InstanceFleetType"];
36770
+ const clusterId = properties?.["ClusterId"];
36771
+ if (fleetType === "TASK" && clusterId) {
36772
+ try {
36773
+ await this.getClient().send(new ModifyInstanceFleetCommand({
36774
+ ClusterId: clusterId,
36775
+ InstanceFleet: {
36776
+ InstanceFleetId: physicalId,
36777
+ TargetOnDemandCapacity: 0,
36778
+ TargetSpotCapacity: 0
36779
+ }
36780
+ }));
36781
+ this.logger.debug(`Scaled EMR TASK instance fleet ${physicalId} to 0 to release its instances (no standalone delete API exists)`);
36782
+ } catch (error) {
36783
+ if (error instanceof InvalidRequestException) {
36784
+ assertRegionMatch(await this.getClient().config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
36785
+ this.logger.debug(`EMR instance fleet ${physicalId} scale-to-0 skipped (cluster/fleet gone): ${error.message}`);
36786
+ } else this.logger.warn(`Best-effort scale-to-0 of EMR instance fleet ${physicalId} failed: ${error instanceof Error ? error.message : String(error)} — its instances are released when the parent cluster terminates`);
36787
+ }
36788
+ return;
36789
+ }
36790
+ this.logger.debug(`EMR instance fleet ${physicalId} (type ${fleetType ?? "unknown"}) has no standalone delete API; its instances are released when the parent cluster terminates. Removing cdkd state only.`);
36791
+ }
36792
+ async getAttribute(physicalId, _resourceType, attributeName) {
36793
+ if (attributeName === "Id") return physicalId;
36794
+ }
36795
+ /** Total target capacity (On-Demand + Spot) requested for the fleet. */
36796
+ targetCapacity(properties) {
36797
+ return (toNumber(properties["TargetOnDemandCapacity"]) ?? 0) + (toNumber(properties["TargetSpotCapacity"]) ?? 0);
36798
+ }
36799
+ /**
36800
+ * Poll until the fleet is `RUNNING` AND its provisioned capacity
36801
+ * (On-Demand + Spot) has settled at `targetCapacity`. The capacity check is
36802
+ * load-bearing on a resize: right after `ModifyInstanceFleet` the fleet is
36803
+ * still in the PRE-resize `RUNNING` state, so a State-only wait would return
36804
+ * before the resize even starts.
36805
+ *
36806
+ * `atLeast` selects the settle direction:
36807
+ * - `true` (create / scale-UP): ready when `provisioned >= targetCapacity`
36808
+ * (`>=`, not `==`, because a weighted-capacity allocation may overshoot).
36809
+ * - `false` (scale-DOWN): ready when `provisioned <= targetCapacity` — the
36810
+ * stale pre-resize provisioned capacity is ABOVE the new lower target, so
36811
+ * an `>=` check would return instantly before instances drain.
36812
+ *
36813
+ * A `targetCapacity` of 0 on the up path (never valid for a real create —
36814
+ * at least one target must be > 0) degrades to a State-only wait.
36815
+ */
36816
+ async waitForFleetReady(clusterId, fleetId, logicalId, resourceType, targetCapacity, atLeast) {
36817
+ const startTime = Date.now();
36818
+ const transientState = { count: 0 };
36819
+ while (Date.now() - startTime < this.maxWaitMs) {
36820
+ const fleet = await this.findFleetForPoll(clusterId, fleetId, transientState);
36821
+ const state = fleet?.Status?.State;
36822
+ const provisioned = (fleet?.ProvisionedOnDemandCapacity ?? 0) + (fleet?.ProvisionedSpotCapacity ?? 0);
36823
+ const capacityReady = atLeast ? provisioned >= targetCapacity : provisioned <= targetCapacity;
36824
+ if (state && READY_STATES.has(state) && capacityReady) return;
36825
+ if (state && FAILED_STATES.has(state)) throw new ProvisioningError(`EMR instance fleet ${fleetId} entered failed state ${state}: ${fleet?.Status?.StateChangeReason?.Message ?? "no state-change reason reported"}`, resourceType, logicalId, fleetId);
36826
+ this.logger.debug(`EMR instance fleet ${fleetId} state: ${state ?? "unknown"}, provisioned ${provisioned}/${targetCapacity}, waiting...`);
36827
+ await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
36828
+ }
36829
+ throw new ProvisioningError(`Timed out waiting for EMR instance fleet ${fleetId} to reach RUNNING with capacity ${targetCapacity} (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, fleetId);
36830
+ }
36831
+ /**
36832
+ * `ListInstanceFleets` (paginated) for the cluster, returning the single
36833
+ * fleet whose `Id` matches. Absorbs up to `maxConsecutiveTransient`
36834
+ * consecutive transient errors (throttle / 5xx / reset) so a single blip
36835
+ * during a 10-minute poll does not spuriously fail the create.
36836
+ */
36837
+ async findFleetForPoll(clusterId, fleetId, transientState, maxConsecutiveTransient = 5) {
36838
+ try {
36839
+ let marker;
36840
+ do {
36841
+ const resp = await this.getClient().send(new ListInstanceFleetsCommand({
36842
+ ClusterId: clusterId,
36843
+ ...marker && { Marker: marker }
36844
+ }));
36845
+ const found = (resp.InstanceFleets ?? []).find((f) => f.Id === fleetId);
36846
+ if (found) {
36847
+ transientState.count = 0;
36848
+ return found;
36849
+ }
36850
+ marker = resp.Marker;
36851
+ } while (marker);
36852
+ transientState.count = 0;
36853
+ return;
36854
+ } catch (error) {
36855
+ const name = error instanceof Error ? error.name : "";
36856
+ const msg = error instanceof Error ? error.message : String(error);
36857
+ if ((name === "ThrottlingException" || name === "InternalServerException" || name === "InternalServerError" || name === "TimeoutError" || /rate exceeded|too many requests|throttl|timed? ?out|ECONNRESET|EPIPE|socket hang up/i.test(msg)) && transientState.count < maxConsecutiveTransient) {
36858
+ transientState.count += 1;
36859
+ this.logger.debug(`Transient ListInstanceFleets error while polling ${fleetId} (${transientState.count}/${maxConsecutiveTransient}): ${msg} — retrying`);
36860
+ return;
36861
+ }
36862
+ throw error;
36863
+ }
36864
+ }
36865
+ };
36866
+
36153
36867
  //#endregion
36154
36868
  //#region src/provisioning/providers/firehose-provider.ts
36155
36869
  /**
@@ -41762,6 +42476,8 @@ function registerAllProviders(registry) {
41762
42476
  registry.register("AWS::EFS::AccessPoint", efsProvider);
41763
42477
  registry.register("AWS::FSx::FileSystem", new FSxFileSystemProvider());
41764
42478
  registry.register("AWS::EMR::Cluster", new EMRClusterProvider());
42479
+ registry.register("AWS::EMR::InstanceGroupConfig", new EMRInstanceGroupConfigProvider());
42480
+ registry.register("AWS::EMR::InstanceFleetConfig", new EMRInstanceFleetConfigProvider());
41765
42481
  registry.register("AWS::KinesisFirehose::DeliveryStream", new FirehoseProvider());
41766
42482
  registry.register("AWS::CloudTrail::Trail", new CloudTrailProvider());
41767
42483
  registry.register("AWS::CodeBuild::Project", new CodeBuildProvider());
@@ -61042,7 +61758,7 @@ function reorderArgs(argv) {
61042
61758
  async function main() {
61043
61759
  installPipeCloseHandler();
61044
61760
  const program = new Command();
61045
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.249.0");
61761
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.251.0");
61046
61762
  program.addCommand(createBootstrapCommand());
61047
61763
  program.addCommand(createSynthCommand());
61048
61764
  program.addCommand(createListCommand());