@go-to-k/cdkd 0.280.25 → 0.280.26
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-Do4MnkQh.js → asg-provider-BJsjMRaA.js} +2 -2
- package/dist/{asg-provider-Do4MnkQh.js.map → asg-provider-BJsjMRaA.js.map} +1 -1
- package/dist/cli.js +208 -30
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DOjLU2Et.js → deploy-engine-Sb8KbTlA.js} +3 -3
- package/dist/{deploy-engine-DOjLU2Et.js.map → deploy-engine-Sb8KbTlA.js.map} +1 -1
- package/dist/index.d.ts.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 requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-
|
|
2
|
+
import { $ as requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-Sb8KbTlA.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-BJsjMRaA.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, 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";
|
|
34
|
+
import { AddTagsCommand, CreateListenerCommand, CreateLoadBalancerCommand, CreateTargetGroupCommand, DeleteListenerCommand, DeleteLoadBalancerCommand, DeleteTargetGroupCommand, DeregisterTargetsCommand, DescribeCapacityReservationCommand, DescribeListenerAttributesCommand, DescribeListenersCommand, DescribeLoadBalancerAttributesCommand, DescribeLoadBalancersCommand, DescribeTagsCommand, DescribeTargetGroupAttributesCommand, DescribeTargetGroupsCommand, DescribeTargetHealthCommand, 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";
|
|
@@ -28759,8 +28759,8 @@ var ELBv2Provider = class {
|
|
|
28759
28759
|
}));
|
|
28760
28760
|
this.logger.debug(`Applied ${tgAttrDiff.length} TargetGroupAttributes change(s) for ${logicalId}`);
|
|
28761
28761
|
}
|
|
28762
|
-
const newTargets = this.convertTargets(properties["Targets"]);
|
|
28763
|
-
const oldTargets = this.convertTargets(previousProperties["Targets"]);
|
|
28762
|
+
const newTargets = this.convertTargets(properties["Targets"], properties["Port"]);
|
|
28763
|
+
const oldTargets = this.convertTargets(previousProperties["Targets"], properties["Port"]);
|
|
28764
28764
|
const targetKey = (t) => JSON.stringify([
|
|
28765
28765
|
t.Id,
|
|
28766
28766
|
t.Port ?? null,
|
|
@@ -29039,8 +29039,21 @@ var ELBv2Provider = class {
|
|
|
29039
29039
|
* `Port` is numeric-coerced (CFn templates may carry it as a string).
|
|
29040
29040
|
* Returns `[]` for an absent / non-array value so callers can branch on
|
|
29041
29041
|
* `.length`.
|
|
29042
|
-
|
|
29043
|
-
|
|
29042
|
+
*
|
|
29043
|
+
* `groupPort` defaults an OMITTED `Port` to the target group's own port,
|
|
29044
|
+
* which is what AWS substitutes when a target is registered without one.
|
|
29045
|
+
* This is load-bearing for the update diff, not cosmetic: `targetKey` below
|
|
29046
|
+
* keys on `Port ?? null`, so without the default a template-shaped
|
|
29047
|
+
* `[{Id}]` and an AWS-readback-shaped `[{Id, Port: 80}]` describe the SAME
|
|
29048
|
+
* live target under two different keys — and the diff then registers the
|
|
29049
|
+
* "new" one (a no-op, it lands on the group port) and DEREGISTERS the live
|
|
29050
|
+
* one. `cdkd drift --revert` hits exactly that, since it hands `update()`
|
|
29051
|
+
* the AWS snapshot as the previous side and a template-shaped desired side.
|
|
29052
|
+
* Absent for a `lambda` target group (no port), where both sides stay
|
|
29053
|
+
* undefined and therefore still key identically.
|
|
29054
|
+
*/
|
|
29055
|
+
convertTargets(raw, groupPort) {
|
|
29056
|
+
const defaultPort = groupPort === void 0 || groupPort === null || Number.isNaN(Number(groupPort)) ? void 0 : Number(groupPort);
|
|
29044
29057
|
if (!Array.isArray(raw)) return [];
|
|
29045
29058
|
const out = [];
|
|
29046
29059
|
for (const entry of raw) {
|
|
@@ -29049,9 +29062,10 @@ var ELBv2Provider = class {
|
|
|
29049
29062
|
continue;
|
|
29050
29063
|
}
|
|
29051
29064
|
const e = entry;
|
|
29065
|
+
const port = e.Port !== void 0 ? Number(e.Port) : defaultPort;
|
|
29052
29066
|
out.push({
|
|
29053
29067
|
Id: e.Id,
|
|
29054
|
-
...
|
|
29068
|
+
...port !== void 0 && { Port: port },
|
|
29055
29069
|
...e.AvailabilityZone !== void 0 && { AvailabilityZone: e.AvailabilityZone }
|
|
29056
29070
|
});
|
|
29057
29071
|
}
|
|
@@ -29213,16 +29227,129 @@ var ELBv2Provider = class {
|
|
|
29213
29227
|
} catch (err) {
|
|
29214
29228
|
if (this.isNotFoundError(err)) return void 0;
|
|
29215
29229
|
}
|
|
29230
|
+
await this.attachRegisteredTargets(result, physicalId);
|
|
29216
29231
|
await this.attachTags(result, physicalId);
|
|
29217
29232
|
return result;
|
|
29218
29233
|
}
|
|
29219
|
-
|
|
29234
|
+
/**
|
|
29235
|
+
* Read the target group's REGISTERED targets back in CFn `Targets` shape via
|
|
29236
|
+
* `DescribeTargetHealth` (issue
|
|
29237
|
+
* [#1620](https://github.com/go-to-k/cdkd/issues/1620)).
|
|
29238
|
+
*
|
|
29239
|
+
* Two things make this safe to compare, and both were the reason `Targets`
|
|
29240
|
+
* sat in {@link getDriftUnknownPaths} until now:
|
|
29241
|
+
*
|
|
29242
|
+
* - **Order.** AWS does not guarantee a readback order for the target list,
|
|
29243
|
+
* and the drift comparator compares arrays positionally. The type now
|
|
29244
|
+
* declares `Targets` in {@link getDriftUnorderedPaths}, which sorts the
|
|
29245
|
+
* list on BOTH comparison sides — so a reorder is not drift.
|
|
29246
|
+
* - **Draining.** Deregistration is asynchronous: a just-removed target
|
|
29247
|
+
* keeps reporting for minutes with `TargetHealth.State === 'draining'`.
|
|
29248
|
+
* Including one would freeze it into the deploy-time `observedProperties`
|
|
29249
|
+
* snapshot and produce PERMANENT phantom drift against every later read,
|
|
29250
|
+
* once it finally disappears. `draining` means "being removed", so the
|
|
29251
|
+
* registered set deliberately excludes it. Every other state (`initial`
|
|
29252
|
+
* right after `RegisterTargets`, `unused` for a target with no listener,
|
|
29253
|
+
* `unhealthy`, `unavailable`) IS a registered target and is included —
|
|
29254
|
+
* health is not registration.
|
|
29255
|
+
*
|
|
29256
|
+
* Two AWS-SUBSTITUTED values are dropped, because echoing back a value the
|
|
29257
|
+
* template never wrote is phantom drift against a `properties`-fallback
|
|
29258
|
+
* baseline — and, worse, a DESTRUCTIVE one: `updateTargetGroup` keys its
|
|
29259
|
+
* register / deregister diff on the whole `(Id, Port, AvailabilityZone)`
|
|
29260
|
+
* tuple, so one extra member makes the SAME live target read as a different
|
|
29261
|
+
* one and `--revert` deregisters it.
|
|
29262
|
+
*
|
|
29263
|
+
* - `Port` when it equals the target group's own port — what AWS
|
|
29264
|
+
* substitutes for a target registered without one. (`convertTargets`
|
|
29265
|
+
* closes the same gap from the other direction, so a template that DOES
|
|
29266
|
+
* spell the port out still keys identically.)
|
|
29267
|
+
* - `AvailabilityZone` unless the group is `ip`-typed and AWS reported
|
|
29268
|
+
* something other than its `all` default. CFn only accepts the member for
|
|
29269
|
+
* `ip` targets, and `DeregisterTargets` rejects it on an instance group.
|
|
29270
|
+
*
|
|
29271
|
+
* Known bound: if `DescribeTargetHealth` were to return an empty list in the
|
|
29272
|
+
* window right after `RegisterTargets`, the deploy-time snapshot would
|
|
29273
|
+
* freeze `Targets: []` against a template that declares some. Not observed —
|
|
29274
|
+
* `RegisterTargets` is synchronous and the integ's post-deploy drift run
|
|
29275
|
+
* sees all three fixture targets — and left unguarded deliberately, since
|
|
29276
|
+
* treating an empty readback as unreadable would also blind a legitimately
|
|
29277
|
+
* emptied target group.
|
|
29278
|
+
*
|
|
29279
|
+
* On error the key is left ABSENT rather than emitted empty. That is not
|
|
29280
|
+
* silent: against an observed baseline that HOLDS targets, an absent key
|
|
29281
|
+
* still reports them as drifted. It is the honest option available — the
|
|
29282
|
+
* read failed, so the live set is unknown — and it keeps `--revert` from
|
|
29283
|
+
* acting on a fabricated empty list.
|
|
29284
|
+
*/
|
|
29285
|
+
async attachRegisteredTargets(result, targetGroupArn) {
|
|
29286
|
+
try {
|
|
29287
|
+
const resp = await this.getClient().send(new DescribeTargetHealthCommand({ TargetGroupArn: targetGroupArn }));
|
|
29288
|
+
const groupPort = typeof result["Port"] === "number" ? result["Port"] : void 0;
|
|
29289
|
+
const isIpTargetGroup = result["TargetType"] === "ip";
|
|
29290
|
+
const targets = [];
|
|
29291
|
+
for (const desc of resp.TargetHealthDescriptions ?? []) {
|
|
29292
|
+
if (desc.TargetHealth?.State === "draining") continue;
|
|
29293
|
+
const id = desc.Target?.Id;
|
|
29294
|
+
if (typeof id !== "string" || id.length === 0) continue;
|
|
29295
|
+
const port = desc.Target?.Port;
|
|
29296
|
+
const az = desc.Target?.AvailabilityZone;
|
|
29297
|
+
targets.push({
|
|
29298
|
+
Id: id,
|
|
29299
|
+
...port !== void 0 && port !== groupPort && { Port: port },
|
|
29300
|
+
...isIpTargetGroup && az !== void 0 && az !== "all" && { AvailabilityZone: az }
|
|
29301
|
+
});
|
|
29302
|
+
}
|
|
29303
|
+
result["Targets"] = targets;
|
|
29304
|
+
} catch (err) {
|
|
29305
|
+
this.logger.debug(`ELBv2 DescribeTargetHealth(${targetGroupArn}) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
29306
|
+
}
|
|
29307
|
+
}
|
|
29308
|
+
/**
|
|
29309
|
+
* `Targets` is scoped PER RESOURCE (issue
|
|
29310
|
+
* [#1602](https://github.com/go-to-k/cdkd/issues/1602)'s seam), not switched
|
|
29311
|
+
* off for the type: it is compared only for a target group whose TEMPLATE
|
|
29312
|
+
* declares `Targets`.
|
|
29313
|
+
*
|
|
29314
|
+
* The reason is the issue [#1498](https://github.com/go-to-k/cdkd/issues/1498)
|
|
29315
|
+
* class. A target group fronting an ECS service or an ASG declares NO
|
|
29316
|
+
* `Targets` — the sibling resource registers them, and it keeps
|
|
29317
|
+
* re-registering as it scales. Comparing an undeclared target list would
|
|
29318
|
+
* therefore report drift on every scale event of an untouched stack, and
|
|
29319
|
+
* `--revert` would DEREGISTER the tasks the service just placed. The
|
|
29320
|
+
* `undeclaredEmptyObservedKeys` guard only covers the case where the capture
|
|
29321
|
+
* happened to be EMPTY, which for a redeployed running service it is not.
|
|
29322
|
+
*
|
|
29323
|
+
* An absent properties bag falls back to COMPARING, per the method's
|
|
29324
|
+
* contract — hiding real drift is the worse failure, and the only caller
|
|
29325
|
+
* that omits the bag today is not `cdkd drift`.
|
|
29326
|
+
*/
|
|
29327
|
+
getDriftUnknownPaths(resourceType, properties) {
|
|
29220
29328
|
switch (resourceType) {
|
|
29221
29329
|
case "AWS::ElasticLoadBalancingV2::LoadBalancer": return ["EnableCapacityReservationProvisionStabilize"];
|
|
29222
|
-
case "AWS::ElasticLoadBalancingV2::TargetGroup":
|
|
29330
|
+
case "AWS::ElasticLoadBalancingV2::TargetGroup":
|
|
29331
|
+
if (properties !== void 0 && Object.keys(properties).length > 0 && properties["Targets"] === void 0) return ["Targets"];
|
|
29332
|
+
return [];
|
|
29223
29333
|
default: return [];
|
|
29224
29334
|
}
|
|
29225
29335
|
}
|
|
29336
|
+
/**
|
|
29337
|
+
* `Targets` is a semantically UNORDERED set: `RegisterTargets` /
|
|
29338
|
+
* `DeregisterTargets` are set operations (the provider's own update path
|
|
29339
|
+
* key-diffs them rather than comparing positions), and `DescribeTargetHealth`
|
|
29340
|
+
* documents no ordering guarantee. Declared here rather than sorted inside
|
|
29341
|
+
* {@link attachRegisteredTargets} so the sort applies to BOTH comparison
|
|
29342
|
+
* sides — see {@link ResourceProvider.getDriftUnorderedPaths}, whose header
|
|
29343
|
+
* records why one-sided sorting manufactures drift on the
|
|
29344
|
+
* `properties`-fallback baseline.
|
|
29345
|
+
*
|
|
29346
|
+
* `TargetGroupAttributes` needs no declaration: it is a `{Key, Value}` list,
|
|
29347
|
+
* which the shared tag-list canonicalizer already sorts on both sides.
|
|
29348
|
+
*/
|
|
29349
|
+
getDriftUnorderedPaths(resourceType) {
|
|
29350
|
+
if (resourceType !== "AWS::ElasticLoadBalancingV2::TargetGroup") return [];
|
|
29351
|
+
return ["Targets"];
|
|
29352
|
+
}
|
|
29226
29353
|
async readListener(physicalId) {
|
|
29227
29354
|
let listener;
|
|
29228
29355
|
try {
|
|
@@ -51985,10 +52112,11 @@ function createDiffCommand() {
|
|
|
51985
52112
|
* the sibling cdk-real-drift (cdkrd) tool, which hit the same false-positive
|
|
51986
52113
|
* classes against the same kind of AWS-snapshot baseline.
|
|
51987
52114
|
*
|
|
51988
|
-
* Plain-string arrays are NOT canonicalized by the
|
|
51989
|
-
*
|
|
51990
|
-
* semantically unordered sets of plain strings (FSx
|
|
51991
|
-
*
|
|
52115
|
+
* Plain-string arrays and NON-tag object arrays are NOT canonicalized by the
|
|
52116
|
+
* two heuristic passes above, because either can be order-significant. But
|
|
52117
|
+
* several CFn inputs are semantically unordered sets of plain strings (FSx
|
|
52118
|
+
* `WindowsConfiguration.Aliases`) or of objects (ELBv2
|
|
52119
|
+
* `TargetGroup.Targets`), so
|
|
51992
52120
|
* {@link canonicalizeUnorderedArraysAtPaths} sorts them at an explicit,
|
|
51993
52121
|
* provider-declared path list only — an opt-in seam mirroring
|
|
51994
52122
|
* `getDriftUnknownPaths` (see `ResourceProvider.getDriftUnorderedPaths`).
|
|
@@ -52052,10 +52180,11 @@ function matchesPathPrefix(path, entries) {
|
|
|
52052
52180
|
return false;
|
|
52053
52181
|
}
|
|
52054
52182
|
/**
|
|
52055
|
-
* Sort plain-string arrays found at one of the
|
|
52056
|
-
* ONLY there. Unlike the two heuristic passes
|
|
52057
|
-
*
|
|
52058
|
-
* is order-significant
|
|
52183
|
+
* Sort plain-string arrays AND object arrays found at one of the
|
|
52184
|
+
* provider-declared `paths`, and ONLY there. Unlike the two heuristic passes
|
|
52185
|
+
* above, this one is opt-in per resource type via
|
|
52186
|
+
* `ResourceProvider.getDriftUnorderedPaths` — a list is order-significant
|
|
52187
|
+
* unless the provider says otherwise.
|
|
52059
52188
|
*
|
|
52060
52189
|
* Paths use dot-notation for nested keys and are matched by the shared
|
|
52061
52190
|
* {@link matchesPathPrefix} rule, the same one `getDriftUnknownPaths` uses. So
|
|
@@ -52073,21 +52202,68 @@ function matchesPathPrefix(path, entries) {
|
|
|
52073
52202
|
* is strictly more permissive; nothing that matches for ignore-paths fails to
|
|
52074
52203
|
* match here.
|
|
52075
52204
|
*
|
|
52076
|
-
*
|
|
52077
|
-
*
|
|
52078
|
-
*
|
|
52079
|
-
*
|
|
52080
|
-
*
|
|
52081
|
-
*
|
|
52205
|
+
* TWO element shapes are sorted, each only when the array is HOMOGENEOUS in it:
|
|
52206
|
+
*
|
|
52207
|
+
* 1. every element a plain string — sorted lexically;
|
|
52208
|
+
* 2. every element a plain object — sorted by {@link canonicalJson}, a
|
|
52209
|
+
* key-order-independent serialization (issue
|
|
52210
|
+
* [#1620](https://github.com/go-to-k/cdkd/issues/1620)). Key order must not
|
|
52211
|
+
* participate: AWS's readback order for an object's own keys is no more
|
|
52212
|
+
* guaranteed than its order for the list, so sorting on raw
|
|
52213
|
+
* `JSON.stringify` would make the comparison depend on it and reintroduce
|
|
52214
|
+
* the phantom drift this pass exists to remove. `ElasticLoadBalancingV2::
|
|
52215
|
+
* TargetGroup.Targets` is the first consumer.
|
|
52216
|
+
*
|
|
52217
|
+
* A MIXED array (strings and objects, or anything else) is left untouched, so
|
|
52218
|
+
* a mis-declared path can never reorder a heterogeneous list. Nested arrays are
|
|
52219
|
+
* also left alone: an array element that is itself an array is not descended
|
|
52220
|
+
* into, so `{P: [['b','a']]}` never has its INNER list sorted by a `'P'`
|
|
52221
|
+
* declaration. That exclusion is a deliberate decision rather than an
|
|
52222
|
+
* inherited accident — no CFn shape in tree is an array-of-arrays, and an
|
|
52223
|
+
* inner list's own order-significance is a separate question from its
|
|
52224
|
+
* container's, which the single declared path cannot express.
|
|
52082
52225
|
*/
|
|
52083
52226
|
function canonicalizeUnorderedArraysAtPaths(v, paths) {
|
|
52084
52227
|
if (paths.length === 0) return v;
|
|
52085
52228
|
return walkUnordered(v, "", paths);
|
|
52086
52229
|
}
|
|
52230
|
+
/**
|
|
52231
|
+
* Serialize a value with every object's keys emitted in sorted order, so two
|
|
52232
|
+
* structurally equal objects produce the same string regardless of the key
|
|
52233
|
+
* order they were built in. Used ONLY as a sort key — the returned string is
|
|
52234
|
+
* never compared for equality by the drift comparator, which keeps its own
|
|
52235
|
+
* `deepEqual`.
|
|
52236
|
+
*
|
|
52237
|
+
* Keys are emitted `JSON.stringify`-quoted so a key containing `:` or `,`
|
|
52238
|
+
* cannot forge a different object's serialization, and `undefined`-valued
|
|
52239
|
+
* keys are SKIPPED exactly as `JSON.stringify` drops them — one side of the
|
|
52240
|
+
* comparison arrives via a raw SDK response (where an absent member is
|
|
52241
|
+
* `undefined`) and the other via JSON round-tripped state (where it is simply
|
|
52242
|
+
* gone), so without the skip the same target would key two different ways.
|
|
52243
|
+
*/
|
|
52244
|
+
function canonicalJson(v) {
|
|
52245
|
+
if (Array.isArray(v)) return `[${v.map(canonicalJson).join(",")}]`;
|
|
52246
|
+
if (v && typeof v === "object") {
|
|
52247
|
+
const bag = v;
|
|
52248
|
+
return `{${Object.keys(bag).filter((k) => bag[k] !== void 0).sort().map((k) => `${JSON.stringify(k)}:${canonicalJson(bag[k])}`).join(",")}}`;
|
|
52249
|
+
}
|
|
52250
|
+
return JSON.stringify(v) ?? "null";
|
|
52251
|
+
}
|
|
52252
|
+
const isPlainObjectElement = (el) => el !== null && typeof el === "object" && !Array.isArray(el);
|
|
52087
52253
|
function walkUnordered(v, path, paths) {
|
|
52088
52254
|
if (Array.isArray(v)) {
|
|
52089
52255
|
const mapped = v.map((el) => Array.isArray(el) ? el : walkUnordered(el, path, paths));
|
|
52090
|
-
if (mapped.length > 1 && matchesPathPrefix(path, paths)
|
|
52256
|
+
if (mapped.length > 1 && matchesPathPrefix(path, paths)) {
|
|
52257
|
+
if (mapped.every((el) => typeof el === "string")) return [...mapped].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
52258
|
+
if (mapped.every(isPlainObjectElement)) {
|
|
52259
|
+
const keyed = mapped.map((el) => ({
|
|
52260
|
+
el,
|
|
52261
|
+
key: canonicalJson(el)
|
|
52262
|
+
}));
|
|
52263
|
+
keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
52264
|
+
return keyed.map((k) => k.el);
|
|
52265
|
+
}
|
|
52266
|
+
}
|
|
52091
52267
|
return mapped;
|
|
52092
52268
|
}
|
|
52093
52269
|
if (v && typeof v === "object") {
|
|
@@ -52158,10 +52334,12 @@ function walkUnordered(v, path, paths) {
|
|
|
52158
52334
|
* `'VpcConfig.SubnetIds'` excludes only that leaf.
|
|
52159
52335
|
*
|
|
52160
52336
|
* `options.unorderedPaths` is supplied by the provider (via
|
|
52161
|
-
* `getDriftUnorderedPaths`) for
|
|
52162
|
-
*
|
|
52163
|
-
*
|
|
52164
|
-
*
|
|
52337
|
+
* `getDriftUnorderedPaths`) for arrays that are semantically UNORDERED sets —
|
|
52338
|
+
* of plain strings (FSx `WindowsConfiguration.Aliases`) or of OBJECTS (ELBv2
|
|
52339
|
+
* `TargetGroup.Targets`, issue #1620, ordered by a key-order-independent
|
|
52340
|
+
* canonical serialization). Those are sorted on BOTH sides before comparison
|
|
52341
|
+
* so an AWS-side reorder is not phantom drift. Path matching uses the same
|
|
52342
|
+
* prefix rule as `ignorePaths`.
|
|
52165
52343
|
*/
|
|
52166
52344
|
function calculateResourceDrift(stateProperties, awsProperties, options) {
|
|
52167
52345
|
const drifts = [];
|
|
@@ -70417,7 +70595,7 @@ function createMigrateCommand() {
|
|
|
70417
70595
|
*/
|
|
70418
70596
|
function buildProgram() {
|
|
70419
70597
|
const program = new Command();
|
|
70420
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.
|
|
70598
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.26");
|
|
70421
70599
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
70422
70600
|
const { profile } = actionCommand.optsWithGlobals();
|
|
70423
70601
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|