@go-to-k/cdkd 0.280.11 → 0.280.13
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-CN0zTvF5.js → asg-provider-DJSCLI9C.js} +2 -2
- package/dist/{asg-provider-CN0zTvF5.js.map → asg-provider-DJSCLI9C.js.map} +1 -1
- package/dist/cli.js +346 -72
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DHGLmPWH.js → deploy-engine-CE-J9Vlu.js} +14 -16
- package/dist/{deploy-engine-DHGLmPWH.js.map → deploy-engine-CE-J9Vlu.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 applyRoleArnIfSet, A as red, At as AssetManifestLoader, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefault, C as isStatefulRecreateTargetSync, Ct as validateAssetBucketName, D as cyan, Dn as withErrorHandling, Dt as getDockerCmd, E as bold, En as normalizeAwsError, Et as formatDockerLoginError, F as ProviderRegistry, Ft as getLegacyStateBucketName, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_BODY_LIMIT, H as cfnRefValueFromPhysicalId, Ht as resolveUseCdkBootstrapAssets, I as findActionableSilentDrops, It as resolveApp, J as readConfigString, Jt as findLargeInlineResources, K as resolveExplicitPhysicalId, Kt as CFN_TEMPLATE_URL_LIMIT, L as CloudControlProvider, Lt as resolveAutoAssetStorage, M as IAMRoleProvider, Mt as Synthesizer, N as collectInlinePolicyNamesManagedBySiblings, Nt as synthesisStatusMessage, O as gray, Ot as runDockerForeground, P as clearOnUpdateRemoval, Pt as getDefaultStateBucketName, Q as requireConfigString, Qt as processStackMessages, R as slowCcOperationTimeoutMs, Rt as resolveCaptureObservedState, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as parseBootstrapMarker, T as formatResourceLine, Tt as buildDockerImage, U as refStateLookupFromResource, Ut as stateBucketExistenceConfirmed, V as IntrinsicFunctionResolver, Vt as resolveStateBucketWithDefaultAndSource, W as WAFv2WebACLProvider, Wt as warnDeprecatedNoPrefixCliFlag, X as requireConfigArray, Xt as expectedOwnerParam, Y as replayWarn, Yt as uploadCfnTemplate, Z as requireConfigObject, Zt as AssemblyReader, _ as createPreDeleteFinalSnapshot, _n as ProvisioningError, _t as rewriteTemplateAssetReferences, a as DeploymentEventsStore, at as DagBuilder, b as unsupportedFinalSnapshotError, bn as StackHasActiveImportsError, bt as ensureAssetStorage, c as replayFailedOperations, ct as S3StateBackend, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalMigrateError, dt as AssetPublisher, en as resolveBucketRegion, et as DiffCalculator, f as computeImplicitDeleteEdges, fn as LocalStartServiceError, ft as stringifyValue, g as ccRoutedFinalSnapshotError, gn as PartialFailureError, gt as loadPublishableAssetManifest, h as buildFinalSnapshotIdentifier, hn as NestedStackChildDirectDestroyError, ht as createAssetRedirectResolver, i as DeploymentEventsReader, in as setAwsClients, it as isThrottlingError, j as yellow, jt as getDockerImageBySourceHash, k as green, kt as runDockerStreaming, l as replayRollback, ln as DeployCancelledError, lt as rebuildClientForBucketRegion, m as PRE_DELETE_SNAPSHOT_TYPES, mn as MissingCdkCliError, mt as buildAssetRedirectMap, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as getAwsClients, nt as withRetry, o as planFailedOps, on as CdkdError, ot as TemplateParser, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pt as WorkGraph, q as assertRegionMatch, qt as MIGRATE_TMP_PREFIX, r as DeployEngine, rn as resetAwsClients, rt as isRetryableTransientError, s as planRollback, st as LockManager, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as AwsClients, tt as describeTypeWithThrottleRetry, u as withResourceDeadline, un as LocalInvokeBuildError$1, ut as shouldRetainResource, v as isFinalSnapshotError, vn as ResourceTimeoutError, vt as AssetModeResolver, w as renderStatefulReason, wt as validateContainerRepoName, x as extractDeploymentEventError, xn as StackTerminationProtectionError, xt as getBootstrapMarkerKey, y as refusesFinalSnapshot, yn as ResourceUpdateNotSupportedError, yt as BOOTSTRAP_MARKER_PREFIX, z as disableInstanceApiTermination, zt as resolveSkipPrefix } from "./deploy-engine-
|
|
2
|
+
import { $ as applyRoleArnIfSet, A as red, At as AssetManifestLoader, B as isTerminationProtectionPropagationError, Bt as resolveStateBucketWithDefault, C as isStatefulRecreateTargetSync, Ct as validateAssetBucketName, D as cyan, Dn as withErrorHandling, Dt as getDockerCmd, E as bold, En as normalizeAwsError, Et as formatDockerLoginError, F as ProviderRegistry, Ft as getLegacyStateBucketName, G as normalizeAwsTagsToCfn, Gt as CFN_TEMPLATE_BODY_LIMIT, H as cfnRefValueFromPhysicalId, Ht as resolveUseCdkBootstrapAssets, I as findActionableSilentDrops, It as resolveApp, J as readConfigString, Jt as findLargeInlineResources, K as resolveExplicitPhysicalId, Kt as CFN_TEMPLATE_URL_LIMIT, L as CloudControlProvider, Lt as resolveAutoAssetStorage, M as IAMRoleProvider, Mt as Synthesizer, N as collectInlinePolicyNamesManagedBySiblings, Nt as synthesisStatusMessage, O as gray, Ot as runDockerForeground, P as clearOnUpdateRemoval, Pt as getDefaultStateBucketName, Q as requireConfigString, Qt as processStackMessages, R as slowCcOperationTimeoutMs, Rt as resolveCaptureObservedState, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as parseBootstrapMarker, T as formatResourceLine, Tt as buildDockerImage, U as refStateLookupFromResource, Ut as stateBucketExistenceConfirmed, V as IntrinsicFunctionResolver, Vt as resolveStateBucketWithDefaultAndSource, W as WAFv2WebACLProvider, Wt as warnDeprecatedNoPrefixCliFlag, X as requireConfigArray, Xt as expectedOwnerParam, Y as replayWarn, Yt as uploadCfnTemplate, Z as requireConfigObject, Zt as AssemblyReader, _ as createPreDeleteFinalSnapshot, _n as ProvisioningError, _t as rewriteTemplateAssetReferences, a as DeploymentEventsStore, at as DagBuilder, b as unsupportedFinalSnapshotError, bn as StackHasActiveImportsError, bt as ensureAssetStorage, c as replayFailedOperations, ct as S3StateBackend, d as IMPLICIT_DELETE_DEPENDENCIES, dn as LocalMigrateError, dt as AssetPublisher, en as resolveBucketRegion, et as DiffCalculator, f as computeImplicitDeleteEdges, fn as LocalStartServiceError, ft as stringifyValue, g as ccRoutedFinalSnapshotError, gn as PartialFailureError, gt as loadPublishableAssetManifest, h as buildFinalSnapshotIdentifier, hn as NestedStackChildDirectDestroyError, ht as createAssetRedirectResolver, i as DeploymentEventsReader, in as setAwsClients, it as isThrottlingError, j as yellow, jt as getDockerImageBySourceHash, k as green, kt as runDockerStreaming, l as replayRollback, ln as DeployCancelledError, lt as rebuildClientForBucketRegion, m as PRE_DELETE_SNAPSHOT_TYPES, mn as MissingCdkCliError, mt as buildAssetRedirectMap, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as getAwsClients, nt as withRetry, o as planFailedOps, on as CdkdError, ot as TemplateParser, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pt as WorkGraph, q as assertRegionMatch, qt as MIGRATE_TMP_PREFIX, r as DeployEngine, rn as resetAwsClients, rt as isRetryableTransientError, s as planRollback, st as LockManager, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as AwsClients, tt as describeTypeWithThrottleRetry, u as withResourceDeadline, un as LocalInvokeBuildError$1, ut as shouldRetainResource, v as isFinalSnapshotError, vn as ResourceTimeoutError, vt as AssetModeResolver, w as renderStatefulReason, wt as validateContainerRepoName, x as extractDeploymentEventError, xn as StackTerminationProtectionError, xt as getBootstrapMarkerKey, y as refusesFinalSnapshot, yn as ResourceUpdateNotSupportedError, yt as BOOTSTRAP_MARKER_PREFIX, z as disableInstanceApiTermination, zt as resolveSkipPrefix } from "./deploy-engine-CE-J9Vlu.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-DJSCLI9C.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -31,7 +31,7 @@ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
31
31
|
import { execFile, spawn } from "node:child_process";
|
|
32
32
|
import { tmpdir } from "node:os";
|
|
33
33
|
import { AssociateVPCWithHostedZoneCommand, ChangeResourceRecordSetsCommand, ChangeTagsForResourceCommand, CreateHostedZoneCommand, CreateQueryLoggingConfigCommand, DeleteHostedZoneCommand, DeleteQueryLoggingConfigCommand, DisassociateVPCFromHostedZoneCommand, GetHostedZoneCommand, ListHostedZonesByNameCommand, ListQueryLoggingConfigsCommand, ListResourceRecordSetsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$8, Route53Client, UpdateHostedZoneCommentCommand, UpdateHostedZoneFeaturesCommand } from "@aws-sdk/client-route-53";
|
|
34
|
-
import { AddTagsCommand, CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, DeleteListenerCommand, DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DescribeListenerAttributesCommand, DescribeListenersCommand, DescribeLoadBalancerAttributesCommand, DescribeLoadBalancersCommand, DescribeTagsCommand, DescribeTargetGroupsCommand, ElasticLoadBalancingV2Client, ModifyListenerAttributesCommand, ModifyListenerCommand, ModifyLoadBalancerAttributesCommand, ModifyTargetGroupCommand, RemoveTagsCommand, SetIpAddressTypeCommand, SetSecurityGroupsCommand, SetSubnetsCommand, waitUntilLoadBalancerAvailable } from "@aws-sdk/client-elastic-load-balancing-v2";
|
|
34
|
+
import { AddTagsCommand, CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, DeleteListenerCommand, DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DeregisterTargetsCommand, DescribeCapacityReservationCommand, DescribeListenerAttributesCommand, DescribeListenersCommand, DescribeLoadBalancerAttributesCommand, DescribeLoadBalancersCommand, DescribeTagsCommand, DescribeTargetGroupAttributesCommand, DescribeTargetGroupsCommand, ElasticLoadBalancingV2Client, ModifyCapacityReservationCommand, ModifyIpPoolsCommand, ModifyListenerAttributesCommand, ModifyListenerCommand, ModifyLoadBalancerAttributesCommand, ModifyTargetGroupAttributesCommand, ModifyTargetGroupCommand, RegisterTargetsCommand, RemoveTagsCommand, SetIpAddressTypeCommand, SetSecurityGroupsCommand, SetSubnetsCommand, waitUntilLoadBalancerAvailable } from "@aws-sdk/client-elastic-load-balancing-v2";
|
|
35
35
|
import { CreateAliasCommand, CreateKeyCommand, DeleteAliasCommand, DescribeKeyCommand, DisableKeyCommand, DisableKeyRotationCommand, EnableKeyCommand, EnableKeyRotationCommand, GetKeyPolicyCommand, GetKeyRotationStatusCommand, KMSClient, ListAliasesCommand, ListResourceTagsCommand, NotFoundException as NotFoundException$2, PutKeyPolicyCommand, ScheduleKeyDeletionCommand, TagResourceCommand as TagResourceCommand$11, UntagResourceCommand as UntagResourceCommand$11, UpdateAliasCommand, UpdateKeyDescriptionCommand } from "@aws-sdk/client-kms";
|
|
36
36
|
import { join as join$1 } from "path";
|
|
37
37
|
import { BatchDeleteImageCommand, CreateRepositoryCommand, DeleteLifecyclePolicyCommand, DeleteRepositoryCommand, DeleteRepositoryPolicyCommand, DescribeImagesCommand as DescribeImagesCommand$1, DescribeRepositoriesCommand, ECRClient, GetAuthorizationTokenCommand, GetLifecyclePolicyCommand, LifecyclePolicyNotFoundException, ListTagsForResourceCommand as ListTagsForResourceCommand$9, PutImageScanningConfigurationCommand, PutImageTagMutabilityCommand, PutLifecyclePolicyCommand, RepositoryNotEmptyException, RepositoryNotFoundException, SetRepositoryPolicyCommand, TagResourceCommand as TagResourceCommand$12, UntagResourceCommand as UntagResourceCommand$12 } from "@aws-sdk/client-ecr";
|
|
@@ -27508,6 +27508,36 @@ var ECSProvider = class {
|
|
|
27508
27508
|
//#endregion
|
|
27509
27509
|
//#region src/provisioning/providers/elbv2-provider.ts
|
|
27510
27510
|
/**
|
|
27511
|
+
* Test seam for the capacity-reservation stabilize poll (mirrors
|
|
27512
|
+
* `finalSnapshotDelays` in ../final-snapshot.ts). Unit tests stub `sleep`
|
|
27513
|
+
* so the poll runs without wall-clock delay.
|
|
27514
|
+
*/
|
|
27515
|
+
const capacityReservationDelays = { sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
|
|
27516
|
+
/**
|
|
27517
|
+
* Documented AWS defaults for TargetGroup attributes, used to reset a
|
|
27518
|
+
* removed `TargetGroupAttributes` entry. Unlike ModifyLoadBalancerAttributes
|
|
27519
|
+
* / ModifyListenerAttributes, ModifyTargetGroupAttributes REJECTS an empty
|
|
27520
|
+
* `Value` ("A target group attribute value must be specified" — live-verified
|
|
27521
|
+
* 2026-08-11), so clearing an override requires sending the documented
|
|
27522
|
+
* default explicitly. Keys whose default is target-type-dependent or
|
|
27523
|
+
* undocumented are deliberately absent — a removal of those warns and
|
|
27524
|
+
* retains the live value instead of guessing.
|
|
27525
|
+
* Source: ELBv2 API reference, TargetGroupAttribute key table.
|
|
27526
|
+
*/
|
|
27527
|
+
const TARGET_GROUP_ATTRIBUTE_DEFAULTS = {
|
|
27528
|
+
"deregistration_delay.timeout_seconds": "300",
|
|
27529
|
+
"deregistration_delay.connection_termination.enabled": "false",
|
|
27530
|
+
"stickiness.enabled": "false",
|
|
27531
|
+
"stickiness.lb_cookie.duration_seconds": "86400",
|
|
27532
|
+
"stickiness.app_cookie.duration_seconds": "86400",
|
|
27533
|
+
"load_balancing.algorithm.type": "round_robin",
|
|
27534
|
+
"load_balancing.algorithm.anomaly_mitigation": "off",
|
|
27535
|
+
"load_balancing.cross_zone.enabled": "use_load_balancer_configuration",
|
|
27536
|
+
"slow_start.duration_seconds": "0",
|
|
27537
|
+
"lambda.multi_value_headers.enabled": "false",
|
|
27538
|
+
"proxy_protocol_v2.enabled": "false"
|
|
27539
|
+
};
|
|
27540
|
+
/**
|
|
27511
27541
|
* AWS ELBv2 Provider
|
|
27512
27542
|
*
|
|
27513
27543
|
* Implements resource provisioning for ELBv2 resources:
|
|
@@ -27540,7 +27570,12 @@ var ELBv2Provider = class {
|
|
|
27540
27570
|
"Type",
|
|
27541
27571
|
"IpAddressType",
|
|
27542
27572
|
"LoadBalancerAttributes",
|
|
27543
|
-
"Tags"
|
|
27573
|
+
"Tags",
|
|
27574
|
+
"EnablePrefixForIpv6SourceNat",
|
|
27575
|
+
"EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic",
|
|
27576
|
+
"Ipv4IpamPoolId",
|
|
27577
|
+
"MinimumLoadBalancerCapacity",
|
|
27578
|
+
"EnableCapacityReservationProvisionStabilize"
|
|
27544
27579
|
])],
|
|
27545
27580
|
["AWS::ElasticLoadBalancingV2::TargetGroup", /* @__PURE__ */ new Set([
|
|
27546
27581
|
"Protocol",
|
|
@@ -27558,7 +27593,11 @@ var ELBv2Provider = class {
|
|
|
27558
27593
|
"UnhealthyThresholdCount",
|
|
27559
27594
|
"Matcher",
|
|
27560
27595
|
"Name",
|
|
27561
|
-
"Tags"
|
|
27596
|
+
"Tags",
|
|
27597
|
+
"IpAddressType",
|
|
27598
|
+
"TargetControlPort",
|
|
27599
|
+
"TargetGroupAttributes",
|
|
27600
|
+
"Targets"
|
|
27562
27601
|
])],
|
|
27563
27602
|
["AWS::ElasticLoadBalancingV2::Listener", /* @__PURE__ */ new Set([
|
|
27564
27603
|
"LoadBalancerArn",
|
|
@@ -27614,6 +27653,7 @@ var ELBv2Provider = class {
|
|
|
27614
27653
|
try {
|
|
27615
27654
|
const tags = this.extractTags(properties);
|
|
27616
27655
|
const lbName = generateResourceNameWithFallback(properties["Name"], logicalId, { maxLength: 32 });
|
|
27656
|
+
const ipv4IpamPoolId = properties["Ipv4IpamPoolId"];
|
|
27617
27657
|
const lb = (await this.getClient().send(new CreateLoadBalancerCommand({
|
|
27618
27658
|
Name: lbName,
|
|
27619
27659
|
Subnets: properties["Subnets"],
|
|
@@ -27622,6 +27662,8 @@ var ELBv2Provider = class {
|
|
|
27622
27662
|
Scheme: properties["Scheme"],
|
|
27623
27663
|
Type: properties["Type"],
|
|
27624
27664
|
IpAddressType: properties["IpAddressType"],
|
|
27665
|
+
EnablePrefixForIpv6SourceNat: properties["EnablePrefixForIpv6SourceNat"],
|
|
27666
|
+
...ipv4IpamPoolId !== void 0 && { IpamPools: { Ipv4IpamPoolId: ipv4IpamPoolId } },
|
|
27625
27667
|
...tags.length > 0 && { Tags: tags }
|
|
27626
27668
|
}))).LoadBalancers?.[0];
|
|
27627
27669
|
if (!lb || !lb.LoadBalancerArn) throw new Error("CreateLoadBalancer did not return LoadBalancer ARN");
|
|
@@ -27638,17 +27680,32 @@ var ELBv2Provider = class {
|
|
|
27638
27680
|
}, { LoadBalancerArns: [lbArn] });
|
|
27639
27681
|
this.logger.debug(`LoadBalancer ${logicalId} is active`);
|
|
27640
27682
|
} else this.logger.debug(`LoadBalancer ${logicalId} created (skipping active-state wait per --no-wait)`);
|
|
27641
|
-
const lbAttributes = properties["LoadBalancerAttributes"];
|
|
27642
|
-
if (lbAttributes
|
|
27683
|
+
const lbAttributes = this.normalizeAttributes(properties["LoadBalancerAttributes"]);
|
|
27684
|
+
if (lbAttributes.length > 0) {
|
|
27643
27685
|
await this.getClient().send(new ModifyLoadBalancerAttributesCommand({
|
|
27644
27686
|
LoadBalancerArn: lbArn,
|
|
27645
|
-
Attributes: lbAttributes
|
|
27646
|
-
Key: attr.Key,
|
|
27647
|
-
Value: attr.Value
|
|
27648
|
-
}))
|
|
27687
|
+
Attributes: lbAttributes
|
|
27649
27688
|
}));
|
|
27650
27689
|
this.logger.debug(`Applied ${lbAttributes.length} LoadBalancer attributes for ${logicalId}`);
|
|
27651
27690
|
}
|
|
27691
|
+
const enforcePrivateLink = properties["EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic"];
|
|
27692
|
+
if (enforcePrivateLink !== void 0) {
|
|
27693
|
+
await this.getClient().send(new SetSecurityGroupsCommand({
|
|
27694
|
+
LoadBalancerArn: lbArn,
|
|
27695
|
+
SecurityGroups: properties["SecurityGroups"] ?? [],
|
|
27696
|
+
EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic: enforcePrivateLink
|
|
27697
|
+
}));
|
|
27698
|
+
this.logger.debug(`Applied EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic=${enforcePrivateLink} for ${logicalId}`);
|
|
27699
|
+
}
|
|
27700
|
+
const minCapacity = properties["MinimumLoadBalancerCapacity"];
|
|
27701
|
+
if (minCapacity?.CapacityUnits !== void 0) {
|
|
27702
|
+
await this.getClient().send(new ModifyCapacityReservationCommand({
|
|
27703
|
+
LoadBalancerArn: lbArn,
|
|
27704
|
+
MinimumLoadBalancerCapacity: { CapacityUnits: Number(minCapacity.CapacityUnits) }
|
|
27705
|
+
}));
|
|
27706
|
+
this.logger.debug(`Requested capacity reservation of ${minCapacity.CapacityUnits} LCU for ${logicalId}`);
|
|
27707
|
+
if (isTruthyCfnBoolean(properties["EnableCapacityReservationProvisionStabilize"]) && process.env["CDKD_NO_WAIT"] !== "true") await this.waitForCapacityReservationProvisioned(lbArn, logicalId);
|
|
27708
|
+
}
|
|
27652
27709
|
} catch (innerError) {
|
|
27653
27710
|
try {
|
|
27654
27711
|
await this.getClient().send(new DeleteLoadBalancerCommand({ LoadBalancerArn: lbArn }));
|
|
@@ -27680,7 +27737,12 @@ var ELBv2Provider = class {
|
|
|
27680
27737
|
"SubnetMappings",
|
|
27681
27738
|
"SecurityGroups",
|
|
27682
27739
|
"IpAddressType",
|
|
27683
|
-
"Tags"
|
|
27740
|
+
"Tags",
|
|
27741
|
+
"EnablePrefixForIpv6SourceNat",
|
|
27742
|
+
"EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic",
|
|
27743
|
+
"Ipv4IpamPoolId",
|
|
27744
|
+
"MinimumLoadBalancerCapacity",
|
|
27745
|
+
"EnableCapacityReservationProvisionStabilize"
|
|
27684
27746
|
]);
|
|
27685
27747
|
const stripHandled = (p) => {
|
|
27686
27748
|
const out = {};
|
|
@@ -27688,19 +27750,7 @@ var ELBv2Provider = class {
|
|
|
27688
27750
|
return out;
|
|
27689
27751
|
};
|
|
27690
27752
|
if (JSON.stringify(stripHandled(properties)) !== JSON.stringify(stripHandled(previousProperties))) throw new ResourceUpdateNotSupportedError("AWS::ElasticLoadBalancingV2::LoadBalancer", logicalId, "ELBv2 LoadBalancer Name / Type / Scheme are immutable on AWS — none of the ELBv2 Modify* / Set* APIs accept these fields; they are fixed at creation. cdkd handles LoadBalancerAttributes / Subnets / SubnetMappings / SecurityGroups / IpAddressType / Tags in-place; for Name / Type / Scheme re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.");
|
|
27691
|
-
const
|
|
27692
|
-
const oldAttrs = previousProperties["LoadBalancerAttributes"] ?? [];
|
|
27693
|
-
const newAttrMap = new Map(newAttrs.map((a) => [a.Key, a.Value]));
|
|
27694
|
-
const oldAttrMap = new Map(oldAttrs.map((a) => [a.Key, a.Value]));
|
|
27695
|
-
const submittedAttrs = [];
|
|
27696
|
-
for (const [k, v] of newAttrMap) if (oldAttrMap.get(k) !== v) submittedAttrs.push({
|
|
27697
|
-
Key: k,
|
|
27698
|
-
Value: v
|
|
27699
|
-
});
|
|
27700
|
-
for (const [k] of oldAttrMap) if (!newAttrMap.has(k)) submittedAttrs.push({
|
|
27701
|
-
Key: k,
|
|
27702
|
-
Value: ""
|
|
27703
|
-
});
|
|
27753
|
+
const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["LoadBalancerAttributes"]), this.normalizeAttributes(previousProperties["LoadBalancerAttributes"]));
|
|
27704
27754
|
if (submittedAttrs.length > 0) {
|
|
27705
27755
|
await this.getClient().send(new ModifyLoadBalancerAttributesCommand({
|
|
27706
27756
|
LoadBalancerArn: physicalId,
|
|
@@ -27712,21 +27762,28 @@ var ELBv2Provider = class {
|
|
|
27712
27762
|
const oldSubnets = previousProperties["Subnets"];
|
|
27713
27763
|
const newMappings = properties["SubnetMappings"];
|
|
27714
27764
|
const oldMappings = previousProperties["SubnetMappings"];
|
|
27765
|
+
const newIpv6SourceNat = properties["EnablePrefixForIpv6SourceNat"];
|
|
27766
|
+
const oldIpv6SourceNat = previousProperties["EnablePrefixForIpv6SourceNat"];
|
|
27715
27767
|
const subnetsChanged = JSON.stringify(newSubnets) !== JSON.stringify(oldSubnets);
|
|
27716
27768
|
const mappingsChanged = JSON.stringify(newMappings) !== JSON.stringify(oldMappings);
|
|
27717
|
-
if (subnetsChanged || mappingsChanged) {
|
|
27769
|
+
if (subnetsChanged || mappingsChanged || newIpv6SourceNat !== void 0 && newIpv6SourceNat !== oldIpv6SourceNat) {
|
|
27718
27770
|
await this.getClient().send(new SetSubnetsCommand({
|
|
27719
27771
|
LoadBalancerArn: physicalId,
|
|
27720
|
-
...newMappings && newMappings.length > 0 ? { SubnetMappings: newMappings } : { Subnets: newSubnets }
|
|
27772
|
+
...newMappings && newMappings.length > 0 ? { SubnetMappings: newMappings } : { Subnets: newSubnets },
|
|
27773
|
+
...newIpv6SourceNat !== void 0 && { EnablePrefixForIpv6SourceNat: newIpv6SourceNat }
|
|
27721
27774
|
}));
|
|
27722
27775
|
this.logger.debug(`Updated Subnets / SubnetMappings for ${logicalId}`);
|
|
27723
27776
|
}
|
|
27724
27777
|
const newSGs = properties["SecurityGroups"];
|
|
27725
27778
|
const oldSGs = previousProperties["SecurityGroups"];
|
|
27726
|
-
|
|
27779
|
+
const newEnforce = properties["EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic"];
|
|
27780
|
+
const oldEnforce = previousProperties["EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic"];
|
|
27781
|
+
const enforceChanged = newEnforce !== void 0 && newEnforce !== oldEnforce;
|
|
27782
|
+
if (JSON.stringify(newSGs) !== JSON.stringify(oldSGs) || enforceChanged) {
|
|
27727
27783
|
await this.getClient().send(new SetSecurityGroupsCommand({
|
|
27728
27784
|
LoadBalancerArn: physicalId,
|
|
27729
|
-
SecurityGroups: newSGs ?? []
|
|
27785
|
+
SecurityGroups: newSGs ?? [],
|
|
27786
|
+
...newEnforce !== void 0 && { EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic: newEnforce }
|
|
27730
27787
|
}));
|
|
27731
27788
|
this.logger.debug(`Updated SecurityGroups for ${logicalId}`);
|
|
27732
27789
|
}
|
|
@@ -27739,12 +27796,64 @@ var ELBv2Provider = class {
|
|
|
27739
27796
|
}));
|
|
27740
27797
|
this.logger.debug(`Updated IpAddressType for ${logicalId}`);
|
|
27741
27798
|
}
|
|
27799
|
+
const newIpamPool = properties["Ipv4IpamPoolId"];
|
|
27800
|
+
if (newIpamPool !== previousProperties["Ipv4IpamPoolId"]) {
|
|
27801
|
+
await this.getClient().send(new ModifyIpPoolsCommand({
|
|
27802
|
+
LoadBalancerArn: physicalId,
|
|
27803
|
+
...newIpamPool !== void 0 ? { IpamPools: { Ipv4IpamPoolId: newIpamPool } } : { RemoveIpamPools: ["ipv4"] }
|
|
27804
|
+
}));
|
|
27805
|
+
this.logger.debug(newIpamPool !== void 0 ? `Updated Ipv4IpamPoolId for ${logicalId}` : `Removed IPAM pool association for ${logicalId}`);
|
|
27806
|
+
}
|
|
27807
|
+
const newCapacity = properties["MinimumLoadBalancerCapacity"];
|
|
27808
|
+
const oldCapacity = previousProperties["MinimumLoadBalancerCapacity"];
|
|
27809
|
+
const newCapacityUnits = newCapacity?.CapacityUnits !== void 0 ? Number(newCapacity.CapacityUnits) : void 0;
|
|
27810
|
+
if (newCapacityUnits !== (oldCapacity?.CapacityUnits !== void 0 ? Number(oldCapacity.CapacityUnits) : void 0)) {
|
|
27811
|
+
await this.getClient().send(new ModifyCapacityReservationCommand({
|
|
27812
|
+
LoadBalancerArn: physicalId,
|
|
27813
|
+
...newCapacityUnits !== void 0 ? { MinimumLoadBalancerCapacity: { CapacityUnits: newCapacityUnits } } : { ResetCapacityReservation: true }
|
|
27814
|
+
}));
|
|
27815
|
+
this.logger.debug(newCapacityUnits !== void 0 ? `Requested capacity reservation of ${newCapacityUnits} LCU for ${logicalId}` : `Reset capacity reservation for ${logicalId}`);
|
|
27816
|
+
if (newCapacityUnits !== void 0 && isTruthyCfnBoolean(properties["EnableCapacityReservationProvisionStabilize"]) && process.env["CDKD_NO_WAIT"] !== "true") await this.waitForCapacityReservationProvisioned(physicalId, logicalId);
|
|
27817
|
+
}
|
|
27742
27818
|
await this.applyTagDiff(physicalId, previousProperties["Tags"], properties["Tags"]);
|
|
27743
27819
|
return {
|
|
27744
27820
|
physicalId,
|
|
27745
27821
|
wasReplaced: false
|
|
27746
27822
|
};
|
|
27747
27823
|
}
|
|
27824
|
+
/**
|
|
27825
|
+
* Poll DescribeCapacityReservation until every zonal state reports
|
|
27826
|
+
* `provisioned` — the semantics of the CFn-only
|
|
27827
|
+
* `EnableCapacityReservationProvisionStabilize` flag (no SDK member; it
|
|
27828
|
+
* opts the deploy into waiting for the reservation instead of returning
|
|
27829
|
+
* while zones are still `pending`). Bounded at ~10 min / 15s interval;
|
|
27830
|
+
* a timeout WARNS and continues (the reservation keeps provisioning
|
|
27831
|
+
* asynchronously and the ModifyCapacityReservation was accepted), while a
|
|
27832
|
+
* `failed` zonal state throws — that reservation will never provision.
|
|
27833
|
+
*/
|
|
27834
|
+
async waitForCapacityReservationProvisioned(lbArn, logicalId) {
|
|
27835
|
+
const maxAttempts = 40;
|
|
27836
|
+
const intervalMs = 15e3;
|
|
27837
|
+
this.logger.debug(`Waiting for capacity reservation of ${logicalId} to provision...`);
|
|
27838
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
27839
|
+
let zones;
|
|
27840
|
+
try {
|
|
27841
|
+
zones = (await this.getClient().send(new DescribeCapacityReservationCommand({ LoadBalancerArn: lbArn }))).CapacityReservationState ?? [];
|
|
27842
|
+
} catch (probeError) {
|
|
27843
|
+
this.logger.debug(`DescribeCapacityReservation for ${logicalId} failed transiently (attempt ${attempt + 1}/${maxAttempts}): ${probeError instanceof Error ? probeError.message : String(probeError)}`);
|
|
27844
|
+
await capacityReservationDelays.sleep(intervalMs);
|
|
27845
|
+
continue;
|
|
27846
|
+
}
|
|
27847
|
+
const failed = zones.find((z) => z.State?.Code === "failed");
|
|
27848
|
+
if (failed) throw new Error(`Capacity reservation for ${logicalId} failed in ${failed.AvailabilityZone ?? "an availability zone"}: ${failed.State?.Reason ?? "no reason reported"}`);
|
|
27849
|
+
if (zones.length === 0 || zones.every((z) => z.State?.Code === "provisioned")) {
|
|
27850
|
+
this.logger.debug(`Capacity reservation for ${logicalId} is provisioned`);
|
|
27851
|
+
return;
|
|
27852
|
+
}
|
|
27853
|
+
await capacityReservationDelays.sleep(intervalMs);
|
|
27854
|
+
}
|
|
27855
|
+
this.logger.warn(`Capacity reservation for ${logicalId} did not reach 'provisioned' within ${maxAttempts * intervalMs / 6e4} minutes; continuing (provisioning completes asynchronously)`);
|
|
27856
|
+
}
|
|
27748
27857
|
async deleteLoadBalancer(logicalId, physicalId, resourceType, context) {
|
|
27749
27858
|
this.logger.debug(`Deleting LoadBalancer ${logicalId}: ${physicalId}`);
|
|
27750
27859
|
if (context?.removeProtection === true) try {
|
|
@@ -27793,16 +27902,45 @@ var ELBv2Provider = class {
|
|
|
27793
27902
|
HealthCheckTimeoutSeconds: properties["HealthCheckTimeoutSeconds"] !== void 0 ? Number(properties["HealthCheckTimeoutSeconds"]) : void 0,
|
|
27794
27903
|
HealthyThresholdCount: properties["HealthyThresholdCount"] !== void 0 ? Number(properties["HealthyThresholdCount"]) : void 0,
|
|
27795
27904
|
UnhealthyThresholdCount: properties["UnhealthyThresholdCount"] !== void 0 ? Number(properties["UnhealthyThresholdCount"]) : void 0,
|
|
27905
|
+
IpAddressType: properties["IpAddressType"],
|
|
27906
|
+
TargetControlPort: properties["TargetControlPort"] !== void 0 ? Number(properties["TargetControlPort"]) : void 0,
|
|
27796
27907
|
...matcher && { Matcher: matcher },
|
|
27797
27908
|
...tags.length > 0 && { Tags: tags }
|
|
27798
27909
|
}))).TargetGroups?.[0];
|
|
27799
27910
|
if (!tg || !tg.TargetGroupArn) throw new Error("CreateTargetGroup did not return TargetGroup ARN");
|
|
27800
|
-
|
|
27911
|
+
const tgArn = tg.TargetGroupArn;
|
|
27912
|
+
this.logger.debug(`Successfully created TargetGroup ${logicalId}: ${tgArn}`);
|
|
27913
|
+
try {
|
|
27914
|
+
const tgAttributes = this.normalizeAttributes(properties["TargetGroupAttributes"]);
|
|
27915
|
+
if (tgAttributes.length > 0) {
|
|
27916
|
+
await this.getClient().send(new ModifyTargetGroupAttributesCommand({
|
|
27917
|
+
TargetGroupArn: tgArn,
|
|
27918
|
+
Attributes: tgAttributes
|
|
27919
|
+
}));
|
|
27920
|
+
this.logger.debug(`Applied ${tgAttributes.length} TargetGroup attribute(s) for ${logicalId}`);
|
|
27921
|
+
}
|
|
27922
|
+
const targets = this.convertTargets(properties["Targets"]);
|
|
27923
|
+
if (targets.length > 0) {
|
|
27924
|
+
await this.getClient().send(new RegisterTargetsCommand({
|
|
27925
|
+
TargetGroupArn: tgArn,
|
|
27926
|
+
Targets: targets
|
|
27927
|
+
}));
|
|
27928
|
+
this.logger.debug(`Registered ${targets.length} target(s) for ${logicalId}`);
|
|
27929
|
+
}
|
|
27930
|
+
} catch (innerError) {
|
|
27931
|
+
try {
|
|
27932
|
+
await this.getClient().send(new DeleteTargetGroupCommand({ TargetGroupArn: tgArn }));
|
|
27933
|
+
this.logger.debug(`Cleaned up partially-created TargetGroup ${logicalId} (${tgArn}) after wiring failure`);
|
|
27934
|
+
} catch (cleanupError) {
|
|
27935
|
+
this.logger.warn(`Failed to clean up partially-created TargetGroup ${logicalId} (${tgArn}): ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Manual deletion may be required before the next deploy: aws elbv2 delete-target-group --target-group-arn ${tgArn}`);
|
|
27936
|
+
}
|
|
27937
|
+
throw innerError;
|
|
27938
|
+
}
|
|
27801
27939
|
return {
|
|
27802
|
-
physicalId:
|
|
27940
|
+
physicalId: tgArn,
|
|
27803
27941
|
attributes: {
|
|
27804
|
-
TargetGroupArn:
|
|
27805
|
-
TargetGroupFullName:
|
|
27942
|
+
TargetGroupArn: tgArn,
|
|
27943
|
+
TargetGroupFullName: tgArn.split(":").pop()?.replace("targetgroup/", ""),
|
|
27806
27944
|
TargetGroupName: tg.TargetGroupName
|
|
27807
27945
|
}
|
|
27808
27946
|
};
|
|
@@ -27813,6 +27951,13 @@ var ELBv2Provider = class {
|
|
|
27813
27951
|
}
|
|
27814
27952
|
async updateTargetGroup(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
27815
27953
|
this.logger.debug(`Updating TargetGroup ${logicalId}: ${physicalId}`);
|
|
27954
|
+
const immutableChanged = (key, coerce) => {
|
|
27955
|
+
const next = properties[key];
|
|
27956
|
+
const prev = previousProperties[key];
|
|
27957
|
+
if (coerce) return (next !== void 0 ? Number(next) : void 0) !== (prev !== void 0 ? Number(prev) : void 0);
|
|
27958
|
+
return JSON.stringify(next) !== JSON.stringify(prev);
|
|
27959
|
+
};
|
|
27960
|
+
for (const [immutableKey, coerce] of [["IpAddressType", false], ["TargetControlPort", true]]) if (immutableChanged(immutableKey, coerce)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `ELBv2 TargetGroup ${immutableKey} is immutable on AWS — no Modify* API accepts it; it is fixed at creation. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
|
|
27816
27961
|
try {
|
|
27817
27962
|
const rawMatcher = properties["Matcher"];
|
|
27818
27963
|
const matcher = rawMatcher && (rawMatcher.HttpCode !== void 0 || rawMatcher.GrpcCode !== void 0) ? rawMatcher : void 0;
|
|
@@ -27829,6 +27974,43 @@ var ELBv2Provider = class {
|
|
|
27829
27974
|
UnhealthyThresholdCount: properties["UnhealthyThresholdCount"] !== void 0 ? Number(properties["UnhealthyThresholdCount"]) : void 0,
|
|
27830
27975
|
...matcher && { Matcher: matcher }
|
|
27831
27976
|
}));
|
|
27977
|
+
const tgAttrDiff = this.diffAttributes(this.normalizeAttributes(properties["TargetGroupAttributes"]), this.normalizeAttributes(previousProperties["TargetGroupAttributes"]), (key) => {
|
|
27978
|
+
const fallback = TARGET_GROUP_ATTRIBUTE_DEFAULTS[key];
|
|
27979
|
+
if (fallback === void 0) this.logger.warn(`TargetGroup attribute ${key} was removed from the template but has no documented default cdkd can reset it to — the live value is retained. Set the attribute explicitly to change it.`);
|
|
27980
|
+
return fallback;
|
|
27981
|
+
});
|
|
27982
|
+
if (tgAttrDiff.length > 0) {
|
|
27983
|
+
await this.getClient().send(new ModifyTargetGroupAttributesCommand({
|
|
27984
|
+
TargetGroupArn: physicalId,
|
|
27985
|
+
Attributes: tgAttrDiff
|
|
27986
|
+
}));
|
|
27987
|
+
this.logger.debug(`Applied ${tgAttrDiff.length} TargetGroupAttributes change(s) for ${logicalId}`);
|
|
27988
|
+
}
|
|
27989
|
+
const newTargets = this.convertTargets(properties["Targets"]);
|
|
27990
|
+
const oldTargets = this.convertTargets(previousProperties["Targets"]);
|
|
27991
|
+
const targetKey = (t) => JSON.stringify([
|
|
27992
|
+
t.Id,
|
|
27993
|
+
t.Port ?? null,
|
|
27994
|
+
t.AvailabilityZone ?? null
|
|
27995
|
+
]);
|
|
27996
|
+
const oldTargetKeys = new Set(oldTargets.map(targetKey));
|
|
27997
|
+
const newTargetKeys = new Set(newTargets.map(targetKey));
|
|
27998
|
+
const targetsToRegister = newTargets.filter((t) => !oldTargetKeys.has(targetKey(t)));
|
|
27999
|
+
const targetsToDeregister = oldTargets.filter((t) => !newTargetKeys.has(targetKey(t)));
|
|
28000
|
+
if (targetsToRegister.length > 0) {
|
|
28001
|
+
await this.getClient().send(new RegisterTargetsCommand({
|
|
28002
|
+
TargetGroupArn: physicalId,
|
|
28003
|
+
Targets: targetsToRegister
|
|
28004
|
+
}));
|
|
28005
|
+
this.logger.debug(`Registered ${targetsToRegister.length} target(s) for ${logicalId}`);
|
|
28006
|
+
}
|
|
28007
|
+
if (targetsToDeregister.length > 0) {
|
|
28008
|
+
await this.getClient().send(new DeregisterTargetsCommand({
|
|
28009
|
+
TargetGroupArn: physicalId,
|
|
28010
|
+
Targets: targetsToDeregister
|
|
28011
|
+
}));
|
|
28012
|
+
this.logger.debug(`Deregistered ${targetsToDeregister.length} target(s) for ${logicalId}`);
|
|
28013
|
+
}
|
|
27832
28014
|
const tg = (await this.getClient().send(new DescribeTargetGroupsCommand({ TargetGroupArns: [physicalId] }))).TargetGroups?.[0];
|
|
27833
28015
|
await this.applyTagDiff(physicalId, previousProperties["Tags"], properties["Tags"]);
|
|
27834
28016
|
this.logger.debug(`Successfully updated TargetGroup ${logicalId}`);
|
|
@@ -27927,19 +28109,7 @@ var ELBv2Provider = class {
|
|
|
27927
28109
|
...alpnPolicy && alpnPolicy.length > 0 && { AlpnPolicy: alpnPolicy },
|
|
27928
28110
|
...mutualAuth !== void 0 && { MutualAuthentication: mutualAuth }
|
|
27929
28111
|
}));
|
|
27930
|
-
const
|
|
27931
|
-
const oldAttrs = this.normalizeAttributes(previousProperties["ListenerAttributes"]);
|
|
27932
|
-
const newAttrMap = new Map(newAttrs.map((a) => [a.Key, a.Value]));
|
|
27933
|
-
const oldAttrMap = new Map(oldAttrs.map((a) => [a.Key, a.Value]));
|
|
27934
|
-
const submittedAttrs = [];
|
|
27935
|
-
for (const [k, v] of newAttrMap) if (oldAttrMap.get(k) !== v) submittedAttrs.push({
|
|
27936
|
-
Key: k,
|
|
27937
|
-
Value: v
|
|
27938
|
-
});
|
|
27939
|
-
for (const [k] of oldAttrMap) if (!newAttrMap.has(k)) submittedAttrs.push({
|
|
27940
|
-
Key: k,
|
|
27941
|
-
Value: ""
|
|
27942
|
-
});
|
|
28112
|
+
const submittedAttrs = this.diffAttributes(this.normalizeAttributes(properties["ListenerAttributes"]), this.normalizeAttributes(previousProperties["ListenerAttributes"]));
|
|
27943
28113
|
if (submittedAttrs.length > 0) {
|
|
27944
28114
|
await withRetry(() => this.getClient().send(new ModifyListenerAttributesCommand({
|
|
27945
28115
|
ListenerArn: physicalId,
|
|
@@ -28015,6 +28185,58 @@ var ELBv2Provider = class {
|
|
|
28015
28185
|
return out;
|
|
28016
28186
|
}
|
|
28017
28187
|
/**
|
|
28188
|
+
* Key-diff two normalized `{Key, Value}` attribute lists into the payload
|
|
28189
|
+
* for a Modify*Attributes call: changed values from `newAttrs` win, and
|
|
28190
|
+
* keys present only in `oldAttrs` are pushed back through `removalValue` —
|
|
28191
|
+
* by default the empty string, which ModifyLoadBalancerAttributes /
|
|
28192
|
+
* ModifyListenerAttributes accept as "clear the override". A resolver
|
|
28193
|
+
* returning `undefined` SKIPS the entry (the resolver owns any warn).
|
|
28194
|
+
* An empty return means nothing changed and the call should be skipped.
|
|
28195
|
+
* Shared by the LoadBalancer / TargetGroup / Listener update paths.
|
|
28196
|
+
*/
|
|
28197
|
+
diffAttributes(newAttrs, oldAttrs, removalValue = () => "") {
|
|
28198
|
+
const newAttrMap = new Map(newAttrs.map((a) => [a.Key, a.Value]));
|
|
28199
|
+
const oldAttrMap = new Map(oldAttrs.map((a) => [a.Key, a.Value]));
|
|
28200
|
+
const submitted = [];
|
|
28201
|
+
for (const [k, v] of newAttrMap) if (oldAttrMap.get(k) !== v) submitted.push({
|
|
28202
|
+
Key: k,
|
|
28203
|
+
Value: v
|
|
28204
|
+
});
|
|
28205
|
+
for (const [k] of oldAttrMap) if (!newAttrMap.has(k)) {
|
|
28206
|
+
const value = removalValue(k);
|
|
28207
|
+
if (value !== void 0) submitted.push({
|
|
28208
|
+
Key: k,
|
|
28209
|
+
Value: value
|
|
28210
|
+
});
|
|
28211
|
+
}
|
|
28212
|
+
return submitted;
|
|
28213
|
+
}
|
|
28214
|
+
/**
|
|
28215
|
+
* Normalize a CFn `Targets` value (an array of `{ Id, Port?,
|
|
28216
|
+
* AvailabilityZone? }` objects) into the SDK's `TargetDescription[]` shape.
|
|
28217
|
+
* Entries missing an `Id` are dropped (Id is the only required member);
|
|
28218
|
+
* `Port` is numeric-coerced (CFn templates may carry it as a string).
|
|
28219
|
+
* Returns `[]` for an absent / non-array value so callers can branch on
|
|
28220
|
+
* `.length`.
|
|
28221
|
+
*/
|
|
28222
|
+
convertTargets(raw) {
|
|
28223
|
+
if (!Array.isArray(raw)) return [];
|
|
28224
|
+
const out = [];
|
|
28225
|
+
for (const entry of raw) {
|
|
28226
|
+
if (entry === null || typeof entry !== "object" || typeof entry.Id !== "string" || entry.Id.length === 0) {
|
|
28227
|
+
this.logger.warn(`Dropping malformed TargetGroup Targets entry (missing string Id): ${JSON.stringify(entry)}`);
|
|
28228
|
+
continue;
|
|
28229
|
+
}
|
|
28230
|
+
const e = entry;
|
|
28231
|
+
out.push({
|
|
28232
|
+
Id: e.Id,
|
|
28233
|
+
...e.Port !== void 0 && { Port: Number(e.Port) },
|
|
28234
|
+
...e.AvailabilityZone !== void 0 && { AvailabilityZone: e.AvailabilityZone }
|
|
28235
|
+
});
|
|
28236
|
+
}
|
|
28237
|
+
return out;
|
|
28238
|
+
}
|
|
28239
|
+
/**
|
|
28018
28240
|
* Apply a diff between old and new CFn-shape Tags arrays via ELBv2's
|
|
28019
28241
|
* `AddTags` / `RemoveTags` APIs. Both accept `ResourceArns: [arn]`
|
|
28020
28242
|
* (single ARN), `Tags: [{Key, Value}]` for AddTags, and
|
|
@@ -28112,6 +28334,15 @@ var ELBv2Provider = class {
|
|
|
28112
28334
|
if (lb.Scheme !== void 0) result["Scheme"] = lb.Scheme;
|
|
28113
28335
|
if (lb.Type !== void 0) result["Type"] = lb.Type;
|
|
28114
28336
|
if (lb.IpAddressType !== void 0) result["IpAddressType"] = lb.IpAddressType;
|
|
28337
|
+
if (lb.EnablePrefixForIpv6SourceNat !== void 0) result["EnablePrefixForIpv6SourceNat"] = lb.EnablePrefixForIpv6SourceNat;
|
|
28338
|
+
if (lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic !== void 0) result["EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic"] = lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic;
|
|
28339
|
+
if (lb.IpamPools?.Ipv4IpamPoolId !== void 0) result["Ipv4IpamPoolId"] = lb.IpamPools.Ipv4IpamPoolId;
|
|
28340
|
+
try {
|
|
28341
|
+
const units = (await this.getClient().send(new DescribeCapacityReservationCommand({ LoadBalancerArn: physicalId }))).MinimumLoadBalancerCapacity?.CapacityUnits;
|
|
28342
|
+
if (units !== void 0 && units > 0) result["MinimumLoadBalancerCapacity"] = { CapacityUnits: units };
|
|
28343
|
+
} catch (err) {
|
|
28344
|
+
if (this.isNotFoundError(err)) return void 0;
|
|
28345
|
+
}
|
|
28115
28346
|
try {
|
|
28116
28347
|
result["LoadBalancerAttributes"] = ((await this.getClient().send(new DescribeLoadBalancerAttributesCommand({ LoadBalancerArn: physicalId }))).Attributes ?? []).filter((a) => typeof a.Key === "string" && typeof a.Value === "string").map((a) => ({
|
|
28117
28348
|
Key: a.Key,
|
|
@@ -28147,13 +28378,30 @@ var ELBv2Provider = class {
|
|
|
28147
28378
|
if (tg.HealthCheckTimeoutSeconds !== void 0) result["HealthCheckTimeoutSeconds"] = tg.HealthCheckTimeoutSeconds;
|
|
28148
28379
|
if (tg.HealthyThresholdCount !== void 0) result["HealthyThresholdCount"] = tg.HealthyThresholdCount;
|
|
28149
28380
|
if (tg.UnhealthyThresholdCount !== void 0) result["UnhealthyThresholdCount"] = tg.UnhealthyThresholdCount;
|
|
28381
|
+
if (tg.IpAddressType !== void 0) result["IpAddressType"] = tg.IpAddressType;
|
|
28382
|
+
if (tg.TargetControlPort !== void 0) result["TargetControlPort"] = tg.TargetControlPort;
|
|
28150
28383
|
const matcher = {};
|
|
28151
28384
|
if (tg.Matcher?.HttpCode !== void 0) matcher["HttpCode"] = tg.Matcher.HttpCode;
|
|
28152
28385
|
if (tg.Matcher?.GrpcCode !== void 0) matcher["GrpcCode"] = tg.Matcher.GrpcCode;
|
|
28153
28386
|
result["Matcher"] = matcher;
|
|
28387
|
+
try {
|
|
28388
|
+
result["TargetGroupAttributes"] = ((await this.getClient().send(new DescribeTargetGroupAttributesCommand({ TargetGroupArn: physicalId }))).Attributes ?? []).filter((a) => typeof a.Key === "string" && typeof a.Value === "string").map((a) => ({
|
|
28389
|
+
Key: a.Key,
|
|
28390
|
+
Value: a.Value
|
|
28391
|
+
})).sort((a, b) => a.Key.localeCompare(b.Key));
|
|
28392
|
+
} catch (err) {
|
|
28393
|
+
if (this.isNotFoundError(err)) return void 0;
|
|
28394
|
+
}
|
|
28154
28395
|
await this.attachTags(result, physicalId);
|
|
28155
28396
|
return result;
|
|
28156
28397
|
}
|
|
28398
|
+
getDriftUnknownPaths(resourceType) {
|
|
28399
|
+
switch (resourceType) {
|
|
28400
|
+
case "AWS::ElasticLoadBalancingV2::LoadBalancer": return ["EnableCapacityReservationProvisionStabilize"];
|
|
28401
|
+
case "AWS::ElasticLoadBalancingV2::TargetGroup": return ["Targets"];
|
|
28402
|
+
default: return [];
|
|
28403
|
+
}
|
|
28404
|
+
}
|
|
28157
28405
|
async readListener(physicalId) {
|
|
28158
28406
|
let listener;
|
|
28159
28407
|
try {
|
|
@@ -50256,32 +50504,57 @@ function isIntrinsic(value) {
|
|
|
50256
50504
|
return keys.length === 1 && INTRINSIC_KEYS.has(keys[0]);
|
|
50257
50505
|
}
|
|
50258
50506
|
/**
|
|
50259
|
-
*
|
|
50260
|
-
*
|
|
50261
|
-
*
|
|
50262
|
-
* values actually differ (excluding intrinsic vs resolved mismatches). This
|
|
50263
|
-
* produces a minimal diff showing only real changes.
|
|
50507
|
+
* Per-side rendering rule for a diff side that is NOT a plain object pair
|
|
50508
|
+
* (primitives, arrays, intrinsics). The both-plain-objects case is handled
|
|
50509
|
+
* jointly by {@link stripUnchangedValuePair}, which never delegates it here.
|
|
50264
50510
|
*/
|
|
50265
50511
|
function stripUnchangedValues(value, other) {
|
|
50266
50512
|
if (value === null || value === void 0 || typeof value !== "object") return value;
|
|
50267
50513
|
if (Array.isArray(value)) return value;
|
|
50268
50514
|
if (isIntrinsic(value)) return void 0;
|
|
50269
50515
|
if (isIntrinsic(other)) return void 0;
|
|
50270
|
-
|
|
50271
|
-
|
|
50272
|
-
|
|
50273
|
-
|
|
50274
|
-
|
|
50275
|
-
|
|
50276
|
-
|
|
50277
|
-
|
|
50278
|
-
|
|
50279
|
-
|
|
50280
|
-
|
|
50281
|
-
|
|
50282
|
-
|
|
50516
|
+
return value;
|
|
50517
|
+
}
|
|
50518
|
+
function isPlainNonIntrinsicObject(value) {
|
|
50519
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !isIntrinsic(value);
|
|
50520
|
+
}
|
|
50521
|
+
/**
|
|
50522
|
+
* Strip unchanged and intrinsic-only keys from BOTH sides of a property
|
|
50523
|
+
* change in ONE walk, so the two rendered sides stay symmetric (issue #1608).
|
|
50524
|
+
*
|
|
50525
|
+
* {@link stripUnchangedValues} runs per side, so a PURE KEY ADDITION pruned
|
|
50526
|
+
* the new side down to the added key while the old side — whose own keys are
|
|
50527
|
+
* all unchanged — hit the empty-result fallback and printed the FULL object.
|
|
50528
|
+
* That asymmetry reads as "the whole object is replaced by just the added
|
|
50529
|
+
* key" (i.e. everything else removed), the opposite of what deploy does.
|
|
50530
|
+
* Walking the UNION of keys once yields `old: {}` / `new: {AddedKey: ...}`
|
|
50531
|
+
* for an addition (and the mirror for a removal); the full-value fallback —
|
|
50532
|
+
* kept for sides differing only in key order or intrinsic-valued keys — now
|
|
50533
|
+
* fires only when BOTH sides pruned to nothing, so it can never be one-sided.
|
|
50534
|
+
* Non-object sides (primitives, arrays, intrinsics) keep the existing
|
|
50535
|
+
* per-side semantics via {@link stripUnchangedValues}.
|
|
50536
|
+
*/
|
|
50537
|
+
function stripUnchangedValuePair(oldValue, newValue) {
|
|
50538
|
+
if (!isPlainNonIntrinsicObject(oldValue) || !isPlainNonIntrinsicObject(newValue)) return [stripUnchangedValues(oldValue, newValue), stripUnchangedValues(newValue, oldValue)];
|
|
50539
|
+
const oldResult = {};
|
|
50540
|
+
const newResult = {};
|
|
50541
|
+
const keys = [...Object.keys(oldValue), ...Object.keys(newValue).filter((k) => !Object.hasOwn(oldValue, k))];
|
|
50542
|
+
for (const key of keys) {
|
|
50543
|
+
const o = oldValue[key];
|
|
50544
|
+
const n = newValue[key];
|
|
50545
|
+
if (isIntrinsic(o) || isIntrinsic(n)) continue;
|
|
50546
|
+
if (JSON.stringify(o) === JSON.stringify(n)) continue;
|
|
50547
|
+
if (isPlainNonIntrinsicObject(o) && isPlainNonIntrinsicObject(n)) {
|
|
50548
|
+
const [fo, fn] = stripUnchangedValuePair(o, n);
|
|
50549
|
+
if (fo !== void 0 && JSON.stringify(fo) !== "{}") oldResult[key] = fo;
|
|
50550
|
+
if (fn !== void 0 && JSON.stringify(fn) !== "{}") newResult[key] = fn;
|
|
50551
|
+
} else {
|
|
50552
|
+
if (Object.hasOwn(oldValue, key)) oldResult[key] = o;
|
|
50553
|
+
if (Object.hasOwn(newValue, key)) newResult[key] = n;
|
|
50554
|
+
}
|
|
50283
50555
|
}
|
|
50284
|
-
|
|
50556
|
+
if (Object.keys(oldResult).length === 0 && Object.keys(newResult).length === 0) return [oldValue, newValue];
|
|
50557
|
+
return [oldResult, newResult];
|
|
50285
50558
|
}
|
|
50286
50559
|
/**
|
|
50287
50560
|
* Render one side of a property change for the diff output.
|
|
@@ -50290,18 +50563,18 @@ function stripUnchangedValues(value, other) {
|
|
|
50290
50563
|
* against current state — most commonly a `Ref` / `Fn::GetAtt` to a resource
|
|
50291
50564
|
* this same deploy will CREATE (the CDK logical-id-churn dance: an
|
|
50292
50565
|
* `AWS::ApiGateway::Deployment` hash rotation, a `fn.currentVersion` Lambda
|
|
50293
|
-
* Version). Rendering that via
|
|
50566
|
+
* Version). Rendering that via the strip-unchanged pass collapsed it to
|
|
50294
50567
|
* the literal string `undefined`, which reads as "this property is being
|
|
50295
50568
|
* removed" (issue #1017). Instead, render the raw intrinsic compactly and —
|
|
50296
50569
|
* on the NEW side — annotate that the value only exists after the deploy.
|
|
50297
|
-
* Everything else
|
|
50570
|
+
* Everything else renders the pre-filtered value computed jointly for both
|
|
50571
|
+
* sides by {@link stripUnchangedValuePair}.
|
|
50298
50572
|
*/
|
|
50299
|
-
function renderDiffValue(own,
|
|
50573
|
+
function renderDiffValue(own, filtered, indent, isNewSide) {
|
|
50300
50574
|
if (isIntrinsic(own)) {
|
|
50301
50575
|
const suffix = isNewSide ? " (known after deploy)" : "";
|
|
50302
50576
|
return `${JSON.stringify(own)}${suffix}`;
|
|
50303
50577
|
}
|
|
50304
|
-
const filtered = stripUnchangedValues(own, opposite);
|
|
50305
50578
|
return (JSON.stringify(filtered, null, 2) ?? "undefined").replace(/\n/g, `\n${indent}`);
|
|
50306
50579
|
}
|
|
50307
50580
|
/**
|
|
@@ -50336,8 +50609,9 @@ function renderChangeLines(changes, logFn, ccApiRoutes) {
|
|
|
50336
50609
|
const requiresReplace = propChange.requiresReplacement ? " [requires replacement]" : "";
|
|
50337
50610
|
const propagated = propChange.replacementPropagated ? " [replacement propagated]" : "";
|
|
50338
50611
|
const indent = " ";
|
|
50339
|
-
const
|
|
50340
|
-
const
|
|
50612
|
+
const [oldFiltered, newFiltered] = stripUnchangedValuePair(propChange.oldValue, propChange.newValue);
|
|
50613
|
+
const oldStr = renderDiffValue(propChange.oldValue, oldFiltered, indent, false);
|
|
50614
|
+
const newStr = renderDiffValue(propChange.newValue, newFiltered, indent, true);
|
|
50341
50615
|
logFn(` - ${propChange.path}:${requiresReplace}${propagated}`);
|
|
50342
50616
|
logFn(` old: ${oldStr}`);
|
|
50343
50617
|
logFn(` new: ${newStr}`);
|
|
@@ -68913,7 +69187,7 @@ function createMigrateCommand() {
|
|
|
68913
69187
|
*/
|
|
68914
69188
|
function buildProgram() {
|
|
68915
69189
|
const program = new Command();
|
|
68916
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.
|
|
69190
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.13");
|
|
68917
69191
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
68918
69192
|
const { profile } = actionCommand.optsWithGlobals();
|
|
68919
69193
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|