@go-to-k/cdkd 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +521 -71
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.54.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.52.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -22622,11 +22622,13 @@ import {
|
|
|
22622
22622
|
DeleteStageCommand,
|
|
22623
22623
|
GetStageCommand,
|
|
22624
22624
|
PutMethodCommand,
|
|
22625
|
+
UpdateMethodCommand,
|
|
22625
22626
|
DeleteMethodCommand,
|
|
22626
22627
|
GetMethodCommand,
|
|
22627
22628
|
PutIntegrationCommand,
|
|
22628
22629
|
PutMethodResponseCommand,
|
|
22629
22630
|
CreateAuthorizerCommand,
|
|
22631
|
+
UpdateAuthorizerCommand,
|
|
22630
22632
|
DeleteAuthorizerCommand,
|
|
22631
22633
|
GetAuthorizerCommand,
|
|
22632
22634
|
TagResourceCommand as TagResourceCommand10,
|
|
@@ -22713,7 +22715,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
22713
22715
|
case "AWS::ApiGateway::Account":
|
|
22714
22716
|
return this.updateAccount(logicalId, physicalId, resourceType, properties);
|
|
22715
22717
|
case "AWS::ApiGateway::Authorizer":
|
|
22716
|
-
return this.updateAuthorizer(
|
|
22718
|
+
return this.updateAuthorizer(
|
|
22719
|
+
logicalId,
|
|
22720
|
+
physicalId,
|
|
22721
|
+
resourceType,
|
|
22722
|
+
properties,
|
|
22723
|
+
previousProperties
|
|
22724
|
+
);
|
|
22717
22725
|
case "AWS::ApiGateway::Resource":
|
|
22718
22726
|
return this.updateResource(
|
|
22719
22727
|
logicalId,
|
|
@@ -22733,7 +22741,13 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
22733
22741
|
previousProperties
|
|
22734
22742
|
);
|
|
22735
22743
|
case "AWS::ApiGateway::Method":
|
|
22736
|
-
return this.updateMethod(
|
|
22744
|
+
return this.updateMethod(
|
|
22745
|
+
logicalId,
|
|
22746
|
+
physicalId,
|
|
22747
|
+
resourceType,
|
|
22748
|
+
properties,
|
|
22749
|
+
previousProperties
|
|
22750
|
+
);
|
|
22737
22751
|
default:
|
|
22738
22752
|
throw new ProvisioningError(
|
|
22739
22753
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -22963,22 +22977,94 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
22963
22977
|
}
|
|
22964
22978
|
}
|
|
22965
22979
|
/**
|
|
22966
|
-
* Update an API Gateway Authorizer
|
|
22980
|
+
* Update an API Gateway Authorizer via `UpdateAuthorizerCommand` (RFC 6902
|
|
22981
|
+
* JSON Patch operations).
|
|
22982
|
+
*
|
|
22983
|
+
* Mutable fields (per AWS API Gateway PATCH operations docs):
|
|
22984
|
+
* `/name`, `/authType`, `/authorizerUri`, `/authorizerCredentials`,
|
|
22985
|
+
* `/identitySource`, `/identityValidationExpression`,
|
|
22986
|
+
* `/authorizerResultTtlInSeconds`, `/providerARNs`.
|
|
22967
22987
|
*
|
|
22968
|
-
*
|
|
22969
|
-
*
|
|
22970
|
-
*
|
|
22971
|
-
*
|
|
22972
|
-
*
|
|
22988
|
+
* `Type` and `RestApiId` are immutable (the deploy engine's replacement
|
|
22989
|
+
* path handles those changes via DELETE + CREATE before this method is
|
|
22990
|
+
* called).
|
|
22991
|
+
*
|
|
22992
|
+
* The `gate on !== undefined` pattern (NOT truthy) is load-bearing for
|
|
22993
|
+
* `cdkd drift --revert`: an empty placeholder coming from
|
|
22994
|
+
* `readCurrentStateAuthorizer` (e.g. `IdentitySource: ''` on a Cognito
|
|
22995
|
+
* authorizer) MUST reach AWS as `replace /<field> ''` so a console-side
|
|
22996
|
+
* change away from "" is actually cleared on revert. A truthy gate would
|
|
22997
|
+
* silently drop the empty placeholder and the next drift run would
|
|
22998
|
+
* re-detect the same divergence forever.
|
|
22973
22999
|
*/
|
|
22974
|
-
updateAuthorizer(logicalId,
|
|
22975
|
-
|
|
22976
|
-
|
|
22977
|
-
|
|
23000
|
+
async updateAuthorizer(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23001
|
+
this.logger.debug(`Updating API Gateway Authorizer ${logicalId}: ${physicalId}`);
|
|
23002
|
+
const restApiId = properties["RestApiId"];
|
|
23003
|
+
if (!restApiId) {
|
|
23004
|
+
throw new ProvisioningError(
|
|
23005
|
+
`RestApiId is required to update API Gateway Authorizer ${logicalId}`,
|
|
23006
|
+
resourceType,
|
|
22978
23007
|
logicalId,
|
|
22979
|
-
|
|
22980
|
-
)
|
|
22981
|
-
|
|
23008
|
+
physicalId
|
|
23009
|
+
);
|
|
23010
|
+
}
|
|
23011
|
+
const patchOperations = [];
|
|
23012
|
+
const primitiveFields = [
|
|
23013
|
+
{ key: "Name", path: "/name" },
|
|
23014
|
+
{ key: "AuthType", path: "/authType" },
|
|
23015
|
+
{ key: "AuthorizerUri", path: "/authorizerUri" },
|
|
23016
|
+
{ key: "AuthorizerCredentials", path: "/authorizerCredentials" },
|
|
23017
|
+
{ key: "IdentitySource", path: "/identitySource" },
|
|
23018
|
+
{ key: "IdentityValidationExpression", path: "/identityValidationExpression" },
|
|
23019
|
+
{ key: "AuthorizerResultTtlInSeconds", path: "/authorizerResultTtlInSeconds" }
|
|
23020
|
+
];
|
|
23021
|
+
for (const { key, path } of primitiveFields) {
|
|
23022
|
+
const newVal = properties[key];
|
|
23023
|
+
const prevVal = previousProperties[key];
|
|
23024
|
+
if (newVal !== prevVal) {
|
|
23025
|
+
patchOperations.push({
|
|
23026
|
+
op: "replace",
|
|
23027
|
+
path,
|
|
23028
|
+
value: newVal !== void 0 ? String(newVal) : ""
|
|
23029
|
+
});
|
|
23030
|
+
}
|
|
23031
|
+
}
|
|
23032
|
+
const newArns = properties["ProviderARNs"];
|
|
23033
|
+
const prevArns = previousProperties["ProviderARNs"];
|
|
23034
|
+
const arnsChanged = (newArns?.length ?? 0) !== (prevArns?.length ?? 0) || (newArns ?? []).some((a, i) => a !== prevArns?.[i]);
|
|
23035
|
+
if (arnsChanged) {
|
|
23036
|
+
patchOperations.push({
|
|
23037
|
+
op: "replace",
|
|
23038
|
+
path: "/providerARNs",
|
|
23039
|
+
value: (newArns ?? []).join(",")
|
|
23040
|
+
});
|
|
23041
|
+
}
|
|
23042
|
+
if (patchOperations.length === 0) {
|
|
23043
|
+
this.logger.debug(`No changes detected for API Gateway Authorizer ${logicalId}`);
|
|
23044
|
+
return { physicalId, wasReplaced: false };
|
|
23045
|
+
}
|
|
23046
|
+
try {
|
|
23047
|
+
await this.apiGatewayClient.send(
|
|
23048
|
+
new UpdateAuthorizerCommand({
|
|
23049
|
+
restApiId,
|
|
23050
|
+
authorizerId: physicalId,
|
|
23051
|
+
patchOperations
|
|
23052
|
+
})
|
|
23053
|
+
);
|
|
23054
|
+
this.logger.debug(
|
|
23055
|
+
`Successfully updated API Gateway Authorizer ${logicalId} (${patchOperations.length} patch ops)`
|
|
23056
|
+
);
|
|
23057
|
+
return { physicalId, wasReplaced: false };
|
|
23058
|
+
} catch (error) {
|
|
23059
|
+
const cause = error instanceof Error ? error : void 0;
|
|
23060
|
+
throw new ProvisioningError(
|
|
23061
|
+
`Failed to update API Gateway Authorizer ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
23062
|
+
resourceType,
|
|
23063
|
+
logicalId,
|
|
23064
|
+
physicalId,
|
|
23065
|
+
cause
|
|
23066
|
+
);
|
|
23067
|
+
}
|
|
22982
23068
|
}
|
|
22983
23069
|
/**
|
|
22984
23070
|
* Delete an API Gateway Authorizer
|
|
@@ -23524,22 +23610,106 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
23524
23610
|
}
|
|
23525
23611
|
}
|
|
23526
23612
|
/**
|
|
23527
|
-
* Update an API Gateway Method
|
|
23613
|
+
* Update an API Gateway Method via `UpdateMethodCommand` (RFC 6902 JSON
|
|
23614
|
+
* Patch operations).
|
|
23615
|
+
*
|
|
23616
|
+
* Mutable top-level fields:
|
|
23617
|
+
* `/authorizationType`, `/authorizerId`, `/apiKeyRequired`,
|
|
23618
|
+
* `/operationName`, `/requestValidatorId`.
|
|
23528
23619
|
*
|
|
23529
|
-
*
|
|
23530
|
-
*
|
|
23531
|
-
*
|
|
23532
|
-
*
|
|
23533
|
-
*
|
|
23620
|
+
* Map fields (`RequestParameters`, `RequestModels`) emit per-key
|
|
23621
|
+
* `add` / `remove` / `replace` ops with paths like
|
|
23622
|
+
* `/requestParameters/method.request.querystring.foo`
|
|
23623
|
+
* `/requestModels/application~1json` (slashes escaped per RFC 6901).
|
|
23624
|
+
*
|
|
23625
|
+
* `HttpMethod`, `ResourceId`, `RestApiId` are immutable (replacement
|
|
23626
|
+
* layer handles them via DELETE + CREATE).
|
|
23627
|
+
*
|
|
23628
|
+
* `Integration` and `MethodResponses` are NOT touched here — they are
|
|
23629
|
+
* separate API Gateway sub-resources (`UpdateIntegration` /
|
|
23630
|
+
* `UpdateMethodResponse`) and the cdkd `create()` path treats them as
|
|
23631
|
+
* inline children of the Method. Round-tripping their structurally-
|
|
23632
|
+
* incomplete `{}` placeholders through `updateMethod` would require
|
|
23633
|
+
* destroying / recreating the integration; that work is deferred and
|
|
23634
|
+
* the empty placeholders are blocked from reaching AWS by the
|
|
23635
|
+
* `!== undefined` gate plus the explicit "ignore Integration /
|
|
23636
|
+
* MethodResponses" comment in this method body.
|
|
23637
|
+
*
|
|
23638
|
+
* The `gate on !== undefined` pattern (NOT truthy) is load-bearing for
|
|
23639
|
+
* `cdkd drift --revert`: `ApiKeyRequired: false` and empty-string
|
|
23640
|
+
* placeholders must reach AWS as a real `replace` op so a console-
|
|
23641
|
+
* side toggle is actually cleared on revert.
|
|
23534
23642
|
*/
|
|
23535
|
-
updateMethod(logicalId,
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23643
|
+
async updateMethod(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23644
|
+
this.logger.debug(`Updating API Gateway Method ${logicalId}: ${physicalId}`);
|
|
23645
|
+
const parts = physicalId.split("|");
|
|
23646
|
+
if (parts.length !== 3) {
|
|
23647
|
+
throw new ProvisioningError(
|
|
23648
|
+
`Invalid physicalId format for API Gateway Method ${logicalId}: expected "restApiId|resourceId|httpMethod", got "${physicalId}"`,
|
|
23649
|
+
resourceType,
|
|
23539
23650
|
logicalId,
|
|
23540
|
-
|
|
23541
|
-
)
|
|
23651
|
+
physicalId
|
|
23652
|
+
);
|
|
23653
|
+
}
|
|
23654
|
+
const [restApiId, resourceId, httpMethod] = parts;
|
|
23655
|
+
const patchOperations = [];
|
|
23656
|
+
const primitiveFields = [
|
|
23657
|
+
{ key: "AuthorizationType", path: "/authorizationType" },
|
|
23658
|
+
{ key: "AuthorizerId", path: "/authorizerId" },
|
|
23659
|
+
{ key: "ApiKeyRequired", path: "/apiKeyRequired" },
|
|
23660
|
+
{ key: "OperationName", path: "/operationName" },
|
|
23661
|
+
{ key: "RequestValidatorId", path: "/requestValidatorId" }
|
|
23662
|
+
];
|
|
23663
|
+
for (const { key, path } of primitiveFields) {
|
|
23664
|
+
const newVal = properties[key];
|
|
23665
|
+
const prevVal = previousProperties[key];
|
|
23666
|
+
if (newVal !== prevVal) {
|
|
23667
|
+
patchOperations.push({
|
|
23668
|
+
op: "replace",
|
|
23669
|
+
path,
|
|
23670
|
+
value: newVal !== void 0 ? String(newVal) : ""
|
|
23671
|
+
});
|
|
23672
|
+
}
|
|
23673
|
+
}
|
|
23674
|
+
appendMapPatchOps(
|
|
23675
|
+
patchOperations,
|
|
23676
|
+
"/requestParameters",
|
|
23677
|
+
properties["RequestParameters"] ?? {},
|
|
23678
|
+
previousProperties["RequestParameters"] ?? {}
|
|
23542
23679
|
);
|
|
23680
|
+
appendMapPatchOps(
|
|
23681
|
+
patchOperations,
|
|
23682
|
+
"/requestModels",
|
|
23683
|
+
properties["RequestModels"] ?? {},
|
|
23684
|
+
previousProperties["RequestModels"] ?? {}
|
|
23685
|
+
);
|
|
23686
|
+
if (patchOperations.length === 0) {
|
|
23687
|
+
this.logger.debug(`No changes detected for API Gateway Method ${logicalId}`);
|
|
23688
|
+
return { physicalId, wasReplaced: false };
|
|
23689
|
+
}
|
|
23690
|
+
try {
|
|
23691
|
+
await this.apiGatewayClient.send(
|
|
23692
|
+
new UpdateMethodCommand({
|
|
23693
|
+
restApiId,
|
|
23694
|
+
resourceId,
|
|
23695
|
+
httpMethod,
|
|
23696
|
+
patchOperations
|
|
23697
|
+
})
|
|
23698
|
+
);
|
|
23699
|
+
this.logger.debug(
|
|
23700
|
+
`Successfully updated API Gateway Method ${logicalId} (${patchOperations.length} patch ops)`
|
|
23701
|
+
);
|
|
23702
|
+
return { physicalId, wasReplaced: false };
|
|
23703
|
+
} catch (error) {
|
|
23704
|
+
const cause = error instanceof Error ? error : void 0;
|
|
23705
|
+
throw new ProvisioningError(
|
|
23706
|
+
`Failed to update API Gateway Method ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
23707
|
+
resourceType,
|
|
23708
|
+
logicalId,
|
|
23709
|
+
physicalId,
|
|
23710
|
+
cause
|
|
23711
|
+
);
|
|
23712
|
+
}
|
|
23543
23713
|
}
|
|
23544
23714
|
/**
|
|
23545
23715
|
* Delete an API Gateway Method
|
|
@@ -23866,6 +24036,23 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
23866
24036
|
return null;
|
|
23867
24037
|
}
|
|
23868
24038
|
};
|
|
24039
|
+
function appendMapPatchOps(ops, basePath, next, prev) {
|
|
24040
|
+
const escape = (k) => k.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
24041
|
+
for (const [key, val] of Object.entries(next)) {
|
|
24042
|
+
const path = `${basePath}/${escape(key)}`;
|
|
24043
|
+
const stringValue = String(val);
|
|
24044
|
+
if (!(key in prev)) {
|
|
24045
|
+
ops.push({ op: "add", path, value: stringValue });
|
|
24046
|
+
} else if (String(prev[key]) !== stringValue) {
|
|
24047
|
+
ops.push({ op: "replace", path, value: stringValue });
|
|
24048
|
+
}
|
|
24049
|
+
}
|
|
24050
|
+
for (const key of Object.keys(prev)) {
|
|
24051
|
+
if (!(key in next)) {
|
|
24052
|
+
ops.push({ op: "remove", path: `${basePath}/${escape(key)}` });
|
|
24053
|
+
}
|
|
24054
|
+
}
|
|
24055
|
+
}
|
|
23869
24056
|
|
|
23870
24057
|
// src/provisioning/providers/apigatewayv2-provider.ts
|
|
23871
24058
|
import {
|
|
@@ -31673,8 +31860,10 @@ var ElastiCacheProvider = class {
|
|
|
31673
31860
|
import {
|
|
31674
31861
|
ServiceDiscoveryClient,
|
|
31675
31862
|
CreatePrivateDnsNamespaceCommand,
|
|
31863
|
+
UpdatePrivateDnsNamespaceCommand,
|
|
31676
31864
|
DeleteNamespaceCommand,
|
|
31677
31865
|
CreateServiceCommand as CreateServiceCommand2,
|
|
31866
|
+
UpdateServiceCommand as UpdateServiceCommand2,
|
|
31678
31867
|
DeleteServiceCommand as DeleteServiceCommand2,
|
|
31679
31868
|
GetNamespaceCommand,
|
|
31680
31869
|
GetOperationCommand,
|
|
@@ -31736,12 +31925,18 @@ var ServiceDiscoveryProvider = class {
|
|
|
31736
31925
|
);
|
|
31737
31926
|
}
|
|
31738
31927
|
}
|
|
31739
|
-
update(logicalId, physicalId, resourceType,
|
|
31928
|
+
update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
31740
31929
|
switch (resourceType) {
|
|
31741
31930
|
case "AWS::ServiceDiscovery::PrivateDnsNamespace":
|
|
31742
|
-
return this.updateNamespace(logicalId, physicalId);
|
|
31931
|
+
return this.updateNamespace(logicalId, physicalId, resourceType, properties);
|
|
31743
31932
|
case "AWS::ServiceDiscovery::Service":
|
|
31744
|
-
return this.updateService(
|
|
31933
|
+
return this.updateService(
|
|
31934
|
+
logicalId,
|
|
31935
|
+
physicalId,
|
|
31936
|
+
resourceType,
|
|
31937
|
+
properties,
|
|
31938
|
+
previousProperties
|
|
31939
|
+
);
|
|
31745
31940
|
default:
|
|
31746
31941
|
throw new ProvisioningError(
|
|
31747
31942
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -31824,14 +32019,66 @@ var ServiceDiscoveryProvider = class {
|
|
|
31824
32019
|
);
|
|
31825
32020
|
}
|
|
31826
32021
|
}
|
|
31827
|
-
|
|
31828
|
-
|
|
31829
|
-
|
|
31830
|
-
|
|
32022
|
+
/**
|
|
32023
|
+
* Update a private DNS namespace.
|
|
32024
|
+
*
|
|
32025
|
+
* AWS exposes `UpdatePrivateDnsNamespace` for two mutable surfaces:
|
|
32026
|
+
* - `Description`
|
|
32027
|
+
* - `Properties.DnsProperties.SOA.TTL`
|
|
32028
|
+
*
|
|
32029
|
+
* `Name` and `Vpc` are immutable; the deploy engine's
|
|
32030
|
+
* replacement-detection layer routes those through DELETE+CREATE
|
|
32031
|
+
* before this method is ever called, so we do not validate them here.
|
|
32032
|
+
*
|
|
32033
|
+
* Empty-string Description is intentionally allowed through (`!== undefined`
|
|
32034
|
+
* gate, not truthy) so `cdkd drift --revert` can clear a console-side ADD.
|
|
32035
|
+
*/
|
|
32036
|
+
async updateNamespace(logicalId, physicalId, resourceType, properties) {
|
|
32037
|
+
this.logger.debug(`Updating private DNS namespace ${logicalId}: ${physicalId}`);
|
|
32038
|
+
const client = this.getClient();
|
|
32039
|
+
const namespaceChange = {};
|
|
32040
|
+
if (properties["Description"] !== void 0) {
|
|
32041
|
+
namespaceChange.Description = properties["Description"];
|
|
32042
|
+
}
|
|
32043
|
+
const propsBag = properties["Properties"];
|
|
32044
|
+
const dnsProps = propsBag?.["DnsProperties"];
|
|
32045
|
+
const soa = dnsProps?.["SOA"];
|
|
32046
|
+
if (soa?.TTL !== void 0) {
|
|
32047
|
+
namespaceChange.Properties = {
|
|
32048
|
+
DnsProperties: {
|
|
32049
|
+
SOA: { TTL: Number(soa.TTL) }
|
|
32050
|
+
}
|
|
32051
|
+
};
|
|
32052
|
+
}
|
|
32053
|
+
if (Object.keys(namespaceChange).length === 0) {
|
|
32054
|
+
this.logger.debug(`No mutable diff for PrivateDnsNamespace ${logicalId}, skipping update`);
|
|
32055
|
+
return { physicalId, wasReplaced: false };
|
|
32056
|
+
}
|
|
32057
|
+
try {
|
|
32058
|
+
const response = await client.send(
|
|
32059
|
+
new UpdatePrivateDnsNamespaceCommand({
|
|
32060
|
+
Id: physicalId,
|
|
32061
|
+
Namespace: namespaceChange
|
|
32062
|
+
})
|
|
32063
|
+
);
|
|
32064
|
+
const operationId = response.OperationId;
|
|
32065
|
+
if (operationId) {
|
|
32066
|
+
await this.pollOperation(operationId, logicalId, resourceType);
|
|
32067
|
+
}
|
|
32068
|
+
this.logger.debug(`Successfully updated private DNS namespace ${logicalId}`);
|
|
32069
|
+
return { physicalId, wasReplaced: false };
|
|
32070
|
+
} catch (error) {
|
|
32071
|
+
if (error instanceof ProvisioningError)
|
|
32072
|
+
throw error;
|
|
32073
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32074
|
+
throw new ProvisioningError(
|
|
32075
|
+
`Failed to update private DNS namespace ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32076
|
+
resourceType,
|
|
31831
32077
|
logicalId,
|
|
31832
|
-
|
|
31833
|
-
|
|
31834
|
-
|
|
32078
|
+
physicalId,
|
|
32079
|
+
cause
|
|
32080
|
+
);
|
|
32081
|
+
}
|
|
31835
32082
|
}
|
|
31836
32083
|
async deleteNamespace(logicalId, physicalId, resourceType, context) {
|
|
31837
32084
|
this.logger.debug(`Deleting private DNS namespace ${logicalId}: ${physicalId}`);
|
|
@@ -31926,14 +32173,69 @@ var ServiceDiscoveryProvider = class {
|
|
|
31926
32173
|
);
|
|
31927
32174
|
}
|
|
31928
32175
|
}
|
|
31929
|
-
|
|
31930
|
-
|
|
31931
|
-
|
|
31932
|
-
|
|
32176
|
+
/**
|
|
32177
|
+
* Update a service discovery service.
|
|
32178
|
+
*
|
|
32179
|
+
* Per AWS docs, `UpdateService` accepts a `ServiceChange` body with
|
|
32180
|
+
* `Description`, `DnsConfig.DnsRecords` (TTLs etc. — `NamespaceId` /
|
|
32181
|
+
* `RoutingPolicy` are not part of the change shape and are immutable
|
|
32182
|
+
* here), and `HealthCheckConfig`. `Name` / `NamespaceId` /
|
|
32183
|
+
* `HealthCheckCustomConfig` are immutable on UpdateService — the
|
|
32184
|
+
* replacement-detection layer routes those through DELETE+CREATE.
|
|
32185
|
+
*
|
|
32186
|
+
* Per AWS docs, omitting `DnsRecords` / `HealthCheckConfig` from the
|
|
32187
|
+
* request DELETES that configuration. To preserve fields cdkd is not
|
|
32188
|
+
* actively reverting, we always echo the AWS-current value when the
|
|
32189
|
+
* caller did not supply a change. `cdkd drift --revert` passes the
|
|
32190
|
+
* full AWS-current snapshot as `properties`, so the round-trip is
|
|
32191
|
+
* value-preserving.
|
|
32192
|
+
*/
|
|
32193
|
+
async updateService(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
32194
|
+
this.logger.debug(`Updating service discovery service ${logicalId}: ${physicalId}`);
|
|
32195
|
+
const client = this.getClient();
|
|
32196
|
+
const serviceChange = {};
|
|
32197
|
+
if (properties["Description"] !== void 0) {
|
|
32198
|
+
serviceChange.Description = properties["Description"];
|
|
32199
|
+
}
|
|
32200
|
+
const dnsConfig = properties["DnsConfig"];
|
|
32201
|
+
if (dnsConfig?.DnsRecords !== void 0) {
|
|
32202
|
+
const change = { DnsRecords: dnsConfig.DnsRecords };
|
|
32203
|
+
serviceChange.DnsConfig = change;
|
|
32204
|
+
}
|
|
32205
|
+
if (properties["HealthCheckConfig"] !== void 0) {
|
|
32206
|
+
serviceChange.HealthCheckConfig = properties["HealthCheckConfig"];
|
|
32207
|
+
}
|
|
32208
|
+
if (Object.keys(serviceChange).length === 0) {
|
|
32209
|
+
this.logger.debug(
|
|
32210
|
+
`No mutable diff for ServiceDiscovery Service ${logicalId}, skipping update`
|
|
32211
|
+
);
|
|
32212
|
+
return { physicalId, wasReplaced: false };
|
|
32213
|
+
}
|
|
32214
|
+
try {
|
|
32215
|
+
const response = await client.send(
|
|
32216
|
+
new UpdateServiceCommand2({
|
|
32217
|
+
Id: physicalId,
|
|
32218
|
+
Service: serviceChange
|
|
32219
|
+
})
|
|
32220
|
+
);
|
|
32221
|
+
const operationId = response.OperationId;
|
|
32222
|
+
if (operationId) {
|
|
32223
|
+
await this.pollOperation(operationId, logicalId, resourceType);
|
|
32224
|
+
}
|
|
32225
|
+
this.logger.debug(`Successfully updated service discovery service ${logicalId}`);
|
|
32226
|
+
return { physicalId, wasReplaced: false };
|
|
32227
|
+
} catch (error) {
|
|
32228
|
+
if (error instanceof ProvisioningError)
|
|
32229
|
+
throw error;
|
|
32230
|
+
const cause = error instanceof Error ? error : void 0;
|
|
32231
|
+
throw new ProvisioningError(
|
|
32232
|
+
`Failed to update service discovery service ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
32233
|
+
resourceType,
|
|
31933
32234
|
logicalId,
|
|
31934
|
-
|
|
31935
|
-
|
|
31936
|
-
|
|
32235
|
+
physicalId,
|
|
32236
|
+
cause
|
|
32237
|
+
);
|
|
32238
|
+
}
|
|
31937
32239
|
}
|
|
31938
32240
|
async deleteService(logicalId, physicalId, resourceType, context) {
|
|
31939
32241
|
this.logger.debug(`Deleting service discovery service ${logicalId}: ${physicalId}`);
|
|
@@ -33020,6 +33322,7 @@ var AppSyncProvider = class {
|
|
|
33020
33322
|
import {
|
|
33021
33323
|
GlueClient,
|
|
33022
33324
|
CreateDatabaseCommand,
|
|
33325
|
+
UpdateDatabaseCommand,
|
|
33023
33326
|
DeleteDatabaseCommand,
|
|
33024
33327
|
CreateTableCommand as CreateTableCommand2,
|
|
33025
33328
|
UpdateTableCommand,
|
|
@@ -33066,11 +33369,7 @@ var GlueProvider = class {
|
|
|
33066
33369
|
async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
33067
33370
|
switch (resourceType) {
|
|
33068
33371
|
case "AWS::Glue::Database":
|
|
33069
|
-
|
|
33070
|
-
resourceType,
|
|
33071
|
-
logicalId,
|
|
33072
|
-
"Glue Database updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
33073
|
-
);
|
|
33372
|
+
return this.updateDatabase(logicalId, physicalId, resourceType, properties);
|
|
33074
33373
|
case "AWS::Glue::Table":
|
|
33075
33374
|
return this.updateTable(logicalId, physicalId, resourceType, properties);
|
|
33076
33375
|
default:
|
|
@@ -33121,12 +33420,7 @@ var GlueProvider = class {
|
|
|
33121
33420
|
await this.getClient().send(
|
|
33122
33421
|
new CreateDatabaseCommand({
|
|
33123
33422
|
CatalogId: catalogId,
|
|
33124
|
-
DatabaseInput:
|
|
33125
|
-
Name: databaseName,
|
|
33126
|
-
Description: databaseInput["Description"],
|
|
33127
|
-
LocationUri: databaseInput["LocationUri"],
|
|
33128
|
-
Parameters: databaseInput["Parameters"]
|
|
33129
|
-
}
|
|
33423
|
+
DatabaseInput: this.buildDatabaseInput(databaseInput, databaseName)
|
|
33130
33424
|
})
|
|
33131
33425
|
);
|
|
33132
33426
|
this.logger.debug(`Successfully created Glue Database ${logicalId}: ${databaseName}`);
|
|
@@ -33145,6 +33439,42 @@ var GlueProvider = class {
|
|
|
33145
33439
|
);
|
|
33146
33440
|
}
|
|
33147
33441
|
}
|
|
33442
|
+
async updateDatabase(logicalId, physicalId, resourceType, properties) {
|
|
33443
|
+
this.logger.debug(`Updating Glue Database ${logicalId}: ${physicalId}`);
|
|
33444
|
+
const databaseInput = properties["DatabaseInput"];
|
|
33445
|
+
if (!databaseInput) {
|
|
33446
|
+
throw new ProvisioningError(
|
|
33447
|
+
`DatabaseInput is required for Glue Database update ${logicalId}`,
|
|
33448
|
+
resourceType,
|
|
33449
|
+
logicalId,
|
|
33450
|
+
physicalId
|
|
33451
|
+
);
|
|
33452
|
+
}
|
|
33453
|
+
const catalogId = properties["CatalogId"];
|
|
33454
|
+
try {
|
|
33455
|
+
await this.getClient().send(
|
|
33456
|
+
new UpdateDatabaseCommand({
|
|
33457
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
33458
|
+
Name: physicalId,
|
|
33459
|
+
DatabaseInput: this.buildDatabaseInput(databaseInput, physicalId)
|
|
33460
|
+
})
|
|
33461
|
+
);
|
|
33462
|
+
this.logger.debug(`Successfully updated Glue Database ${logicalId}`);
|
|
33463
|
+
return {
|
|
33464
|
+
physicalId,
|
|
33465
|
+
wasReplaced: false
|
|
33466
|
+
};
|
|
33467
|
+
} catch (error) {
|
|
33468
|
+
const cause = error instanceof Error ? error : void 0;
|
|
33469
|
+
throw new ProvisioningError(
|
|
33470
|
+
`Failed to update Glue Database ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
33471
|
+
resourceType,
|
|
33472
|
+
logicalId,
|
|
33473
|
+
physicalId,
|
|
33474
|
+
cause
|
|
33475
|
+
);
|
|
33476
|
+
}
|
|
33477
|
+
}
|
|
33148
33478
|
async deleteDatabase(logicalId, physicalId, resourceType, properties, context) {
|
|
33149
33479
|
this.logger.debug(`Deleting Glue Database ${logicalId}: ${physicalId}`);
|
|
33150
33480
|
try {
|
|
@@ -33316,6 +33646,31 @@ var GlueProvider = class {
|
|
|
33316
33646
|
}
|
|
33317
33647
|
}
|
|
33318
33648
|
// ─── Helpers ───────────────────────────────────────────────────────
|
|
33649
|
+
/**
|
|
33650
|
+
* Build DatabaseInput for Glue API from CFn template properties.
|
|
33651
|
+
*
|
|
33652
|
+
* Used by both `createDatabase` and `updateDatabase` so the same
|
|
33653
|
+
* field-by-field shape is sent on both paths. Optional fields use
|
|
33654
|
+
* `!== undefined` gates (per `feedback_update_optional_field_undefined_check.md`)
|
|
33655
|
+
* so empty-string Description, empty Parameters map, etc. reach AWS
|
|
33656
|
+
* intact — `cdkd drift --revert` relies on this to clear console-side
|
|
33657
|
+
* additions.
|
|
33658
|
+
*/
|
|
33659
|
+
buildDatabaseInput(databaseInput, fallbackName) {
|
|
33660
|
+
const result = {
|
|
33661
|
+
Name: databaseInput["Name"] ?? fallbackName
|
|
33662
|
+
};
|
|
33663
|
+
if (databaseInput["Description"] !== void 0) {
|
|
33664
|
+
result.Description = databaseInput["Description"];
|
|
33665
|
+
}
|
|
33666
|
+
if (databaseInput["LocationUri"] !== void 0) {
|
|
33667
|
+
result.LocationUri = databaseInput["LocationUri"];
|
|
33668
|
+
}
|
|
33669
|
+
if (databaseInput["Parameters"] !== void 0) {
|
|
33670
|
+
result.Parameters = databaseInput["Parameters"];
|
|
33671
|
+
}
|
|
33672
|
+
return result;
|
|
33673
|
+
}
|
|
33319
33674
|
/**
|
|
33320
33675
|
* Build TableInput for Glue API from CFn template properties
|
|
33321
33676
|
*/
|
|
@@ -34781,10 +35136,12 @@ var KinesisStreamProvider = class {
|
|
|
34781
35136
|
import {
|
|
34782
35137
|
EFSClient,
|
|
34783
35138
|
CreateFileSystemCommand,
|
|
35139
|
+
UpdateFileSystemCommand,
|
|
34784
35140
|
DeleteFileSystemCommand,
|
|
34785
35141
|
CreateMountTargetCommand,
|
|
34786
35142
|
DeleteMountTargetCommand,
|
|
34787
35143
|
DescribeMountTargetsCommand,
|
|
35144
|
+
ModifyMountTargetSecurityGroupsCommand,
|
|
34788
35145
|
CreateAccessPointCommand,
|
|
34789
35146
|
DeleteAccessPointCommand,
|
|
34790
35147
|
DescribeFileSystemsCommand,
|
|
@@ -34842,29 +35199,122 @@ var EFSProvider = class {
|
|
|
34842
35199
|
}
|
|
34843
35200
|
}
|
|
34844
35201
|
/**
|
|
34845
|
-
*
|
|
34846
|
-
*
|
|
34847
|
-
*
|
|
34848
|
-
*
|
|
34849
|
-
*
|
|
34850
|
-
*
|
|
35202
|
+
* Mutable surfaces by resource type:
|
|
35203
|
+
* - `AWS::EFS::FileSystem` → `UpdateFileSystem` (ThroughputMode,
|
|
35204
|
+
* ProvisionedThroughputInMibps). Other property changes
|
|
35205
|
+
* (Encrypted / KmsKeyId / PerformanceMode / etc.) are routed
|
|
35206
|
+
* through DELETE+CREATE by the replacement-detection layer; if a
|
|
35207
|
+
* diff somehow includes them, defensively reject.
|
|
35208
|
+
* - `AWS::EFS::MountTarget` → `ModifyMountTargetSecurityGroups`
|
|
35209
|
+
* (SecurityGroups only). IpAddress / SubnetId / FileSystemId are
|
|
35210
|
+
* immutable.
|
|
35211
|
+
* - `AWS::EFS::AccessPoint` → no mutable surface; AWS recreates on
|
|
35212
|
+
* every change. Reject so `cdkd drift --revert` surfaces a clear
|
|
35213
|
+
* "use --replace" hint.
|
|
34851
35214
|
*/
|
|
34852
|
-
update(logicalId, physicalId, resourceType,
|
|
34853
|
-
|
|
35215
|
+
update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
35216
|
+
switch (resourceType) {
|
|
35217
|
+
case "AWS::EFS::FileSystem":
|
|
35218
|
+
return this.updateFileSystem(
|
|
35219
|
+
logicalId,
|
|
35220
|
+
physicalId,
|
|
35221
|
+
resourceType,
|
|
35222
|
+
properties,
|
|
35223
|
+
previousProperties
|
|
35224
|
+
);
|
|
35225
|
+
case "AWS::EFS::MountTarget":
|
|
35226
|
+
return this.updateMountTarget(logicalId, physicalId, resourceType, properties);
|
|
35227
|
+
case "AWS::EFS::AccessPoint":
|
|
35228
|
+
return Promise.reject(
|
|
35229
|
+
new ResourceUpdateNotSupportedError(
|
|
35230
|
+
resourceType,
|
|
35231
|
+
logicalId,
|
|
35232
|
+
"EFS AccessPoint is recreated on property changes; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
35233
|
+
)
|
|
35234
|
+
);
|
|
35235
|
+
default:
|
|
35236
|
+
throw new ProvisioningError(
|
|
35237
|
+
`Unsupported resource type: ${resourceType}`,
|
|
35238
|
+
resourceType,
|
|
35239
|
+
logicalId,
|
|
35240
|
+
physicalId
|
|
35241
|
+
);
|
|
35242
|
+
}
|
|
35243
|
+
}
|
|
35244
|
+
async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
35245
|
+
const immutableKeys = ["Encrypted", "KmsKeyId", "PerformanceMode"];
|
|
35246
|
+
for (const key of immutableKeys) {
|
|
35247
|
+
const next = properties[key];
|
|
35248
|
+
const prev = previousProperties[key];
|
|
35249
|
+
if (next !== void 0 && prev !== void 0 && JSON.stringify(next) !== JSON.stringify(prev)) {
|
|
35250
|
+
throw new ResourceUpdateNotSupportedError(
|
|
35251
|
+
resourceType,
|
|
35252
|
+
logicalId,
|
|
35253
|
+
`EFS FileSystem ${key} is immutable; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack`
|
|
35254
|
+
);
|
|
35255
|
+
}
|
|
35256
|
+
}
|
|
35257
|
+
const newThroughputMode = properties["ThroughputMode"];
|
|
35258
|
+
const newProvisioned = properties["ProvisionedThroughputInMibps"];
|
|
35259
|
+
const oldThroughputMode = previousProperties["ThroughputMode"];
|
|
35260
|
+
const oldProvisioned = previousProperties["ProvisionedThroughputInMibps"];
|
|
35261
|
+
const throughputModeChanged = newThroughputMode !== void 0 && newThroughputMode !== oldThroughputMode;
|
|
35262
|
+
const provisionedChanged = newProvisioned !== void 0 && newProvisioned !== oldProvisioned;
|
|
35263
|
+
if (!throughputModeChanged && !provisionedChanged) {
|
|
35264
|
+
this.logger.debug(`No mutable diff for EFS FileSystem ${logicalId}, skipping update`);
|
|
35265
|
+
return { physicalId, wasReplaced: false };
|
|
35266
|
+
}
|
|
35267
|
+
this.logger.debug(`Updating EFS FileSystem ${logicalId}: ${physicalId}`);
|
|
35268
|
+
try {
|
|
35269
|
+
await this.getClient().send(
|
|
35270
|
+
new UpdateFileSystemCommand({
|
|
35271
|
+
FileSystemId: physicalId,
|
|
35272
|
+
...throughputModeChanged && { ThroughputMode: newThroughputMode },
|
|
35273
|
+
...provisionedChanged && { ProvisionedThroughputInMibps: newProvisioned }
|
|
35274
|
+
})
|
|
35275
|
+
);
|
|
35276
|
+
await this.waitForFileSystemAvailable(physicalId, logicalId, resourceType);
|
|
35277
|
+
this.logger.debug(`Successfully updated EFS FileSystem ${logicalId}`);
|
|
35278
|
+
return { physicalId, wasReplaced: false };
|
|
35279
|
+
} catch (error) {
|
|
35280
|
+
if (error instanceof ProvisioningError)
|
|
35281
|
+
throw error;
|
|
35282
|
+
const cause = error instanceof Error ? error : void 0;
|
|
34854
35283
|
throw new ProvisioningError(
|
|
34855
|
-
`
|
|
35284
|
+
`Failed to update EFS FileSystem ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
34856
35285
|
resourceType,
|
|
34857
35286
|
logicalId,
|
|
34858
|
-
physicalId
|
|
35287
|
+
physicalId,
|
|
35288
|
+
cause
|
|
34859
35289
|
);
|
|
34860
35290
|
}
|
|
34861
|
-
|
|
34862
|
-
|
|
35291
|
+
}
|
|
35292
|
+
async updateMountTarget(logicalId, physicalId, resourceType, properties) {
|
|
35293
|
+
this.logger.debug(`Updating EFS MountTarget ${logicalId}: ${physicalId}`);
|
|
35294
|
+
const securityGroups = properties["SecurityGroups"];
|
|
35295
|
+
if (securityGroups === void 0) {
|
|
35296
|
+
this.logger.debug(`No mutable diff for EFS MountTarget ${logicalId}, skipping update`);
|
|
35297
|
+
return { physicalId, wasReplaced: false };
|
|
35298
|
+
}
|
|
35299
|
+
try {
|
|
35300
|
+
await this.getClient().send(
|
|
35301
|
+
new ModifyMountTargetSecurityGroupsCommand({
|
|
35302
|
+
MountTargetId: physicalId,
|
|
35303
|
+
SecurityGroups: securityGroups
|
|
35304
|
+
})
|
|
35305
|
+
);
|
|
35306
|
+
this.logger.debug(`Successfully updated EFS MountTarget ${logicalId}`);
|
|
35307
|
+
return { physicalId, wasReplaced: false };
|
|
35308
|
+
} catch (error) {
|
|
35309
|
+
const cause = error instanceof Error ? error : void 0;
|
|
35310
|
+
throw new ProvisioningError(
|
|
35311
|
+
`Failed to update EFS MountTarget ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
34863
35312
|
resourceType,
|
|
34864
35313
|
logicalId,
|
|
34865
|
-
|
|
34866
|
-
|
|
34867
|
-
|
|
35314
|
+
physicalId,
|
|
35315
|
+
cause
|
|
35316
|
+
);
|
|
35317
|
+
}
|
|
34868
35318
|
}
|
|
34869
35319
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
34870
35320
|
switch (resourceType) {
|
|
@@ -45339,7 +45789,7 @@ function reorderArgs(argv) {
|
|
|
45339
45789
|
}
|
|
45340
45790
|
async function main() {
|
|
45341
45791
|
const program = new Command14();
|
|
45342
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
45792
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.54.0");
|
|
45343
45793
|
program.addCommand(createBootstrapCommand());
|
|
45344
45794
|
program.addCommand(createSynthCommand());
|
|
45345
45795
|
program.addCommand(createListCommand());
|