@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/{asg-provider-CMWe8LlY.js → asg-provider-er3xGYRo.js} +2 -2
- package/dist/{asg-provider-CMWe8LlY.js.map → asg-provider-er3xGYRo.js.map} +1 -1
- package/dist/cli.js +816 -100
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DqAyGFJu.js → deploy-engine-D-gBbMiZ.js} +32 -4
- package/dist/{deploy-engine-DqAyGFJu.js.map → deploy-engine-D-gBbMiZ.js.map} +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as 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-
|
|
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-
|
|
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.
|
|
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$
|
|
34414
|
-
const DEFAULT_POLL_INTERVAL_MS$
|
|
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$
|
|
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$
|
|
34585
|
-
this.maxWaitMs = options?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS$
|
|
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$
|
|
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$
|
|
34714
|
+
ImportedFileChunkSize: toNumber$3(config["ImportedFileChunkSize"]),
|
|
34695
34715
|
DeploymentType: config["DeploymentType"],
|
|
34696
34716
|
AutoImportPolicy: config["AutoImportPolicy"],
|
|
34697
|
-
PerUnitStorageThroughput: toNumber$
|
|
34717
|
+
PerUnitStorageThroughput: toNumber$3(config["PerUnitStorageThroughput"]),
|
|
34698
34718
|
DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
|
|
34699
|
-
AutomaticBackupRetentionDays: toNumber$
|
|
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$
|
|
34724
|
+
ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
|
|
34705
34725
|
MetadataConfiguration: metadata ? {
|
|
34706
34726
|
Mode: metadata["Mode"],
|
|
34707
|
-
Iops: toNumber$
|
|
34727
|
+
Iops: toNumber$3(metadata["Iops"])
|
|
34708
34728
|
} : void 0,
|
|
34709
34729
|
DataReadCacheConfiguration: readCache ? {
|
|
34710
34730
|
SizingMode: readCache["SizingMode"],
|
|
34711
|
-
SizeGiB: toNumber$
|
|
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$
|
|
34743
|
+
ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
|
|
34724
34744
|
WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
|
|
34725
34745
|
DailyAutomaticBackupStartTime: config["DailyAutomaticBackupStartTime"],
|
|
34726
|
-
AutomaticBackupRetentionDays: toNumber$
|
|
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$
|
|
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$
|
|
34766
|
+
ThroughputCapacity: toNumber$3(config["ThroughputCapacity"]),
|
|
34747
34767
|
WeeklyMaintenanceStartTime: config["WeeklyMaintenanceStartTime"],
|
|
34748
|
-
HAPairs: toNumber$
|
|
34749
|
-
ThroughputCapacityPerHAPair: toNumber$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
34833
|
-
StorageCapacityQuotaGiB: toNumber$
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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`
|
|
35233
|
-
*
|
|
35234
|
-
*
|
|
35235
|
-
*
|
|
35236
|
-
*
|
|
35237
|
-
*
|
|
35238
|
-
*
|
|
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.
|
|
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
|
-
|
|
35269
|
-
|
|
35270
|
-
|
|
35271
|
-
|
|
35272
|
-
|
|
35273
|
-
|
|
35274
|
-
|
|
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
|
-
|
|
35279
|
-
|
|
35280
|
-
|
|
35281
|
-
|
|
35282
|
-
|
|
35283
|
-
|
|
35284
|
-
|
|
35285
|
-
|
|
35286
|
-
|
|
35287
|
-
|
|
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
|
-
|
|
35291
|
-
|
|
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
|
-
|
|
35297
|
-
|
|
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
|
-
|
|
35303
|
-
|
|
35304
|
-
|
|
35305
|
-
|
|
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.
|
|
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());
|