@go-to-k/cdkd 0.64.0 → 0.66.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 +1138 -1
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.66.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.64.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -56189,6 +56189,26 @@ import {
|
|
|
56189
56189
|
DeleteSecurityConfigurationCommand,
|
|
56190
56190
|
GetSecurityConfigurationCommand,
|
|
56191
56191
|
GetSecurityConfigurationsCommand,
|
|
56192
|
+
CreateJobCommand,
|
|
56193
|
+
UpdateJobCommand,
|
|
56194
|
+
DeleteJobCommand,
|
|
56195
|
+
GetJobCommand,
|
|
56196
|
+
CreateCrawlerCommand,
|
|
56197
|
+
UpdateCrawlerCommand,
|
|
56198
|
+
DeleteCrawlerCommand,
|
|
56199
|
+
GetCrawlerCommand,
|
|
56200
|
+
StartCrawlerScheduleCommand,
|
|
56201
|
+
StopCrawlerScheduleCommand,
|
|
56202
|
+
CreateConnectionCommand,
|
|
56203
|
+
UpdateConnectionCommand,
|
|
56204
|
+
DeleteConnectionCommand,
|
|
56205
|
+
GetConnectionCommand,
|
|
56206
|
+
CreateTriggerCommand,
|
|
56207
|
+
UpdateTriggerCommand,
|
|
56208
|
+
DeleteTriggerCommand,
|
|
56209
|
+
GetTriggerCommand,
|
|
56210
|
+
StartTriggerCommand,
|
|
56211
|
+
StopTriggerCommand,
|
|
56192
56212
|
EntityNotFoundException
|
|
56193
56213
|
} from "@aws-sdk/client-glue";
|
|
56194
56214
|
import { STSClient as STSClient8, GetCallerIdentityCommand as GetCallerIdentityCommand8 } from "@aws-sdk/client-sts";
|
|
@@ -57350,6 +57370,1119 @@ function cleanCfnObject(obj) {
|
|
|
57350
57370
|
}
|
|
57351
57371
|
return out;
|
|
57352
57372
|
}
|
|
57373
|
+
async function buildGlueResourceArn(client, stsClient, resource, name, accountId) {
|
|
57374
|
+
const region = await client.config.region() || process.env["AWS_REGION"] || "us-east-1";
|
|
57375
|
+
const account = accountId ?? await resolveAccountId(stsClient);
|
|
57376
|
+
return `arn:aws:glue:${region}:${account}:${resource}/${name}`;
|
|
57377
|
+
}
|
|
57378
|
+
async function resolveAccountId(stsClient) {
|
|
57379
|
+
const identity = await stsClient.send(new GetCallerIdentityCommand8({}));
|
|
57380
|
+
if (!identity.Account) {
|
|
57381
|
+
throw new Error("Failed to resolve AWS account id from STS");
|
|
57382
|
+
}
|
|
57383
|
+
return identity.Account;
|
|
57384
|
+
}
|
|
57385
|
+
async function fetchGlueTags(client, stsClient, resource, name, accountId, logger) {
|
|
57386
|
+
try {
|
|
57387
|
+
const arn = await buildGlueResourceArn(client, stsClient, resource, name, accountId);
|
|
57388
|
+
const resp = await client.send(new GetTagsCommand({ ResourceArn: arn }));
|
|
57389
|
+
return normalizeAwsTagsToCfn(resp.Tags);
|
|
57390
|
+
} catch (err) {
|
|
57391
|
+
logger.debug(
|
|
57392
|
+
`GetTags failed for ${resource}/${name}: ${err instanceof Error ? err.message : String(err)}`
|
|
57393
|
+
);
|
|
57394
|
+
return [];
|
|
57395
|
+
}
|
|
57396
|
+
}
|
|
57397
|
+
var GlueJobProvider = class {
|
|
57398
|
+
client;
|
|
57399
|
+
stsClient;
|
|
57400
|
+
cachedAccountId;
|
|
57401
|
+
providerRegion = process.env["AWS_REGION"];
|
|
57402
|
+
logger = getLogger().child("GlueJobProvider");
|
|
57403
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
57404
|
+
[
|
|
57405
|
+
"AWS::Glue::Job",
|
|
57406
|
+
/* @__PURE__ */ new Set([
|
|
57407
|
+
"Name",
|
|
57408
|
+
"Role",
|
|
57409
|
+
"Command",
|
|
57410
|
+
"Description",
|
|
57411
|
+
"MaxCapacity",
|
|
57412
|
+
"MaxRetries",
|
|
57413
|
+
"Timeout",
|
|
57414
|
+
"ExecutionProperty",
|
|
57415
|
+
"GlueVersion",
|
|
57416
|
+
"NumberOfWorkers",
|
|
57417
|
+
"WorkerType",
|
|
57418
|
+
"DefaultArguments",
|
|
57419
|
+
"NonOverridableArguments",
|
|
57420
|
+
"Connections",
|
|
57421
|
+
"LogUri",
|
|
57422
|
+
"SecurityConfiguration",
|
|
57423
|
+
"NotificationProperty",
|
|
57424
|
+
"ExecutionClass",
|
|
57425
|
+
"JobMode",
|
|
57426
|
+
"JobRunQueuingEnabled",
|
|
57427
|
+
"MaintenanceWindow",
|
|
57428
|
+
"AllocatedCapacity",
|
|
57429
|
+
"SourceControlDetails",
|
|
57430
|
+
"Tags"
|
|
57431
|
+
])
|
|
57432
|
+
]
|
|
57433
|
+
]);
|
|
57434
|
+
getClient() {
|
|
57435
|
+
if (!this.client) {
|
|
57436
|
+
this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
57437
|
+
}
|
|
57438
|
+
return this.client;
|
|
57439
|
+
}
|
|
57440
|
+
getStsClient() {
|
|
57441
|
+
if (!this.stsClient) {
|
|
57442
|
+
this.stsClient = new STSClient8(this.providerRegion ? { region: this.providerRegion } : {});
|
|
57443
|
+
}
|
|
57444
|
+
return this.stsClient;
|
|
57445
|
+
}
|
|
57446
|
+
async create(logicalId, resourceType, properties) {
|
|
57447
|
+
this.logger.debug(`Creating Glue Job ${logicalId}`);
|
|
57448
|
+
const name = properties["Name"] ?? logicalId;
|
|
57449
|
+
const role = properties["Role"];
|
|
57450
|
+
const command = properties["Command"];
|
|
57451
|
+
if (!role) {
|
|
57452
|
+
throw new ProvisioningError(
|
|
57453
|
+
`Role is required for Glue Job ${logicalId}`,
|
|
57454
|
+
resourceType,
|
|
57455
|
+
logicalId
|
|
57456
|
+
);
|
|
57457
|
+
}
|
|
57458
|
+
if (!command) {
|
|
57459
|
+
throw new ProvisioningError(
|
|
57460
|
+
`Command is required for Glue Job ${logicalId}`,
|
|
57461
|
+
resourceType,
|
|
57462
|
+
logicalId
|
|
57463
|
+
);
|
|
57464
|
+
}
|
|
57465
|
+
try {
|
|
57466
|
+
const tags = cfnTagsToMap(properties["Tags"]);
|
|
57467
|
+
await this.getClient().send(
|
|
57468
|
+
new CreateJobCommand({
|
|
57469
|
+
Name: name,
|
|
57470
|
+
Role: role,
|
|
57471
|
+
Command: buildJobCommand(command),
|
|
57472
|
+
...buildJobCommonFields(properties),
|
|
57473
|
+
...tags && { Tags: tags }
|
|
57474
|
+
})
|
|
57475
|
+
);
|
|
57476
|
+
this.logger.debug(`Successfully created Glue Job ${logicalId}: ${name}`);
|
|
57477
|
+
return { physicalId: name, attributes: {} };
|
|
57478
|
+
} catch (error) {
|
|
57479
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57480
|
+
throw new ProvisioningError(
|
|
57481
|
+
`Failed to create Glue Job ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57482
|
+
resourceType,
|
|
57483
|
+
logicalId,
|
|
57484
|
+
void 0,
|
|
57485
|
+
cause
|
|
57486
|
+
);
|
|
57487
|
+
}
|
|
57488
|
+
}
|
|
57489
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
57490
|
+
this.logger.debug(`Updating Glue Job ${logicalId}: ${physicalId}`);
|
|
57491
|
+
try {
|
|
57492
|
+
const command = properties["Command"];
|
|
57493
|
+
const update = {
|
|
57494
|
+
...command !== void 0 && { Command: buildJobCommand(command) },
|
|
57495
|
+
...buildJobCommonFields(properties),
|
|
57496
|
+
// Role is required at create but mutable on update; include only when defined
|
|
57497
|
+
...properties["Role"] !== void 0 && { Role: properties["Role"] }
|
|
57498
|
+
};
|
|
57499
|
+
await this.getClient().send(new UpdateJobCommand({ JobName: physicalId, JobUpdate: update }));
|
|
57500
|
+
const oldTags = cfnTagsToMap(previousProperties["Tags"]) ?? {};
|
|
57501
|
+
const newTags = cfnTagsToMap(properties["Tags"]) ?? {};
|
|
57502
|
+
await this.applyTagDiff(physicalId, oldTags, newTags);
|
|
57503
|
+
return { physicalId, wasReplaced: false };
|
|
57504
|
+
} catch (error) {
|
|
57505
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57506
|
+
throw new ProvisioningError(
|
|
57507
|
+
`Failed to update Glue Job ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57508
|
+
resourceType,
|
|
57509
|
+
logicalId,
|
|
57510
|
+
physicalId,
|
|
57511
|
+
cause
|
|
57512
|
+
);
|
|
57513
|
+
}
|
|
57514
|
+
}
|
|
57515
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
57516
|
+
this.logger.debug(`Deleting Glue Job ${logicalId}: ${physicalId}`);
|
|
57517
|
+
try {
|
|
57518
|
+
await this.getClient().send(new DeleteJobCommand({ JobName: physicalId }));
|
|
57519
|
+
} catch (error) {
|
|
57520
|
+
if (error instanceof EntityNotFoundException) {
|
|
57521
|
+
const clientRegion = await this.getClient().config.region();
|
|
57522
|
+
assertRegionMatch(
|
|
57523
|
+
clientRegion,
|
|
57524
|
+
context?.expectedRegion,
|
|
57525
|
+
resourceType,
|
|
57526
|
+
logicalId,
|
|
57527
|
+
physicalId
|
|
57528
|
+
);
|
|
57529
|
+
this.logger.debug(`Glue Job ${physicalId} does not exist, skipping deletion`);
|
|
57530
|
+
return;
|
|
57531
|
+
}
|
|
57532
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57533
|
+
throw new ProvisioningError(
|
|
57534
|
+
`Failed to delete Glue Job ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57535
|
+
resourceType,
|
|
57536
|
+
logicalId,
|
|
57537
|
+
physicalId,
|
|
57538
|
+
cause
|
|
57539
|
+
);
|
|
57540
|
+
}
|
|
57541
|
+
}
|
|
57542
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- explicit-override-only intentionally has no AWS calls
|
|
57543
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
57544
|
+
if (attributeName === "Id" || attributeName === "Ref" || attributeName === "Name") {
|
|
57545
|
+
return physicalId;
|
|
57546
|
+
}
|
|
57547
|
+
return void 0;
|
|
57548
|
+
}
|
|
57549
|
+
/**
|
|
57550
|
+
* Read the AWS-current Glue Job in CFn-property shape.
|
|
57551
|
+
*
|
|
57552
|
+
* Always-emit placeholders for user-controllable top-level keys per
|
|
57553
|
+
* PR #145 (`?? '' | [] | {}`) so the v3 `observedProperties` baseline
|
|
57554
|
+
* detects console-side ADDs to fields that weren't templated. Tags
|
|
57555
|
+
* always emit `[]` (PR H pattern).
|
|
57556
|
+
*/
|
|
57557
|
+
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
57558
|
+
let job;
|
|
57559
|
+
try {
|
|
57560
|
+
const resp = await this.getClient().send(new GetJobCommand({ JobName: physicalId }));
|
|
57561
|
+
job = resp.Job;
|
|
57562
|
+
} catch (err) {
|
|
57563
|
+
if (err instanceof EntityNotFoundException)
|
|
57564
|
+
return void 0;
|
|
57565
|
+
throw err;
|
|
57566
|
+
}
|
|
57567
|
+
if (!job)
|
|
57568
|
+
return void 0;
|
|
57569
|
+
const result = {
|
|
57570
|
+
Name: job.Name ?? physicalId,
|
|
57571
|
+
Role: job.Role ?? "",
|
|
57572
|
+
Command: pickDefined({
|
|
57573
|
+
Name: job.Command?.Name,
|
|
57574
|
+
ScriptLocation: job.Command?.ScriptLocation,
|
|
57575
|
+
PythonVersion: job.Command?.PythonVersion,
|
|
57576
|
+
Runtime: job.Command?.Runtime
|
|
57577
|
+
}),
|
|
57578
|
+
Description: job.Description ?? "",
|
|
57579
|
+
LogUri: job.LogUri ?? "",
|
|
57580
|
+
DefaultArguments: job.DefaultArguments ?? {},
|
|
57581
|
+
NonOverridableArguments: job.NonOverridableArguments ?? {},
|
|
57582
|
+
Connections: { Connections: job.Connections?.Connections ?? [] },
|
|
57583
|
+
MaxRetries: job.MaxRetries ?? 0,
|
|
57584
|
+
Timeout: job.Timeout ?? 0,
|
|
57585
|
+
ExecutionProperty: { MaxConcurrentRuns: job.ExecutionProperty?.MaxConcurrentRuns ?? 1 },
|
|
57586
|
+
NotificationProperty: { NotifyDelayAfter: job.NotificationProperty?.NotifyDelayAfter ?? 0 },
|
|
57587
|
+
GlueVersion: job.GlueVersion ?? "",
|
|
57588
|
+
NumberOfWorkers: job.NumberOfWorkers ?? 0,
|
|
57589
|
+
WorkerType: job.WorkerType ?? "",
|
|
57590
|
+
MaxCapacity: job.MaxCapacity ?? 0,
|
|
57591
|
+
AllocatedCapacity: job.AllocatedCapacity ?? 0,
|
|
57592
|
+
SecurityConfiguration: job.SecurityConfiguration ?? "",
|
|
57593
|
+
ExecutionClass: job.ExecutionClass ?? "",
|
|
57594
|
+
JobMode: job.JobMode ?? "",
|
|
57595
|
+
JobRunQueuingEnabled: job.JobRunQueuingEnabled ?? false,
|
|
57596
|
+
MaintenanceWindow: job.MaintenanceWindow ?? "",
|
|
57597
|
+
SourceControlDetails: job.SourceControlDetails ? pickDefined(job.SourceControlDetails) : {}
|
|
57598
|
+
};
|
|
57599
|
+
result["Tags"] = await fetchGlueTags(
|
|
57600
|
+
this.getClient(),
|
|
57601
|
+
this.getStsClient(),
|
|
57602
|
+
"job",
|
|
57603
|
+
job.Name ?? physicalId,
|
|
57604
|
+
this.cachedAccountId,
|
|
57605
|
+
this.logger
|
|
57606
|
+
);
|
|
57607
|
+
return result;
|
|
57608
|
+
}
|
|
57609
|
+
async applyTagDiff(physicalId, oldTags, newTags) {
|
|
57610
|
+
const arn = await buildGlueResourceArn(
|
|
57611
|
+
this.getClient(),
|
|
57612
|
+
this.getStsClient(),
|
|
57613
|
+
"job",
|
|
57614
|
+
physicalId,
|
|
57615
|
+
this.cachedAccountId
|
|
57616
|
+
);
|
|
57617
|
+
const toAdd = {};
|
|
57618
|
+
const toRemove = [];
|
|
57619
|
+
for (const [k, v] of Object.entries(newTags)) {
|
|
57620
|
+
if (oldTags[k] !== v)
|
|
57621
|
+
toAdd[k] = v;
|
|
57622
|
+
}
|
|
57623
|
+
for (const k of Object.keys(oldTags)) {
|
|
57624
|
+
if (!(k in newTags))
|
|
57625
|
+
toRemove.push(k);
|
|
57626
|
+
}
|
|
57627
|
+
if (Object.keys(toAdd).length > 0 || toRemove.length > 0) {
|
|
57628
|
+
const { TagResourceCommand: TagResourceCommand17, UntagResourceCommand: UntagResourceCommand16 } = await import("@aws-sdk/client-glue");
|
|
57629
|
+
if (Object.keys(toAdd).length > 0) {
|
|
57630
|
+
await this.getClient().send(new TagResourceCommand17({ ResourceArn: arn, TagsToAdd: toAdd }));
|
|
57631
|
+
}
|
|
57632
|
+
if (toRemove.length > 0) {
|
|
57633
|
+
await this.getClient().send(
|
|
57634
|
+
new UntagResourceCommand16({ ResourceArn: arn, TagsToRemove: toRemove })
|
|
57635
|
+
);
|
|
57636
|
+
}
|
|
57637
|
+
}
|
|
57638
|
+
}
|
|
57639
|
+
async import(input) {
|
|
57640
|
+
const explicitName = input.knownPhysicalId ?? input.properties["Name"];
|
|
57641
|
+
if (!explicitName)
|
|
57642
|
+
return null;
|
|
57643
|
+
try {
|
|
57644
|
+
await this.getClient().send(new GetJobCommand({ JobName: explicitName }));
|
|
57645
|
+
return { physicalId: explicitName, attributes: {} };
|
|
57646
|
+
} catch (err) {
|
|
57647
|
+
if (err instanceof EntityNotFoundException)
|
|
57648
|
+
return null;
|
|
57649
|
+
throw err;
|
|
57650
|
+
}
|
|
57651
|
+
}
|
|
57652
|
+
};
|
|
57653
|
+
function buildJobCommand(c) {
|
|
57654
|
+
const result = {};
|
|
57655
|
+
if (c["Name"] !== void 0)
|
|
57656
|
+
result.Name = c["Name"];
|
|
57657
|
+
if (c["ScriptLocation"] !== void 0)
|
|
57658
|
+
result.ScriptLocation = c["ScriptLocation"];
|
|
57659
|
+
if (c["PythonVersion"] !== void 0)
|
|
57660
|
+
result.PythonVersion = c["PythonVersion"];
|
|
57661
|
+
if (c["Runtime"] !== void 0)
|
|
57662
|
+
result.Runtime = c["Runtime"];
|
|
57663
|
+
return result;
|
|
57664
|
+
}
|
|
57665
|
+
function buildJobCommonFields(p) {
|
|
57666
|
+
const r = {};
|
|
57667
|
+
const passThrough = [
|
|
57668
|
+
"JobMode",
|
|
57669
|
+
"JobRunQueuingEnabled",
|
|
57670
|
+
"Description",
|
|
57671
|
+
"LogUri",
|
|
57672
|
+
"DefaultArguments",
|
|
57673
|
+
"NonOverridableArguments",
|
|
57674
|
+
"MaxRetries",
|
|
57675
|
+
"AllocatedCapacity",
|
|
57676
|
+
"Timeout",
|
|
57677
|
+
"MaxCapacity",
|
|
57678
|
+
"WorkerType",
|
|
57679
|
+
"NumberOfWorkers",
|
|
57680
|
+
"SecurityConfiguration",
|
|
57681
|
+
"GlueVersion",
|
|
57682
|
+
"ExecutionClass",
|
|
57683
|
+
"MaintenanceWindow"
|
|
57684
|
+
];
|
|
57685
|
+
for (const k of passThrough) {
|
|
57686
|
+
if (p[k] !== void 0) {
|
|
57687
|
+
r[k] = p[k];
|
|
57688
|
+
}
|
|
57689
|
+
}
|
|
57690
|
+
if (p["ExecutionProperty"] !== void 0) {
|
|
57691
|
+
r.ExecutionProperty = p["ExecutionProperty"];
|
|
57692
|
+
}
|
|
57693
|
+
if (p["Connections"] !== void 0) {
|
|
57694
|
+
const conn = p["Connections"];
|
|
57695
|
+
r.Connections = { Connections: conn["Connections"] ?? [] };
|
|
57696
|
+
}
|
|
57697
|
+
if (p["NotificationProperty"] !== void 0) {
|
|
57698
|
+
r.NotificationProperty = p["NotificationProperty"];
|
|
57699
|
+
}
|
|
57700
|
+
if (p["SourceControlDetails"] !== void 0) {
|
|
57701
|
+
r.SourceControlDetails = p["SourceControlDetails"];
|
|
57702
|
+
}
|
|
57703
|
+
return r;
|
|
57704
|
+
}
|
|
57705
|
+
function cfnTagsToMap(tagsInput) {
|
|
57706
|
+
if (tagsInput === void 0)
|
|
57707
|
+
return void 0;
|
|
57708
|
+
const out = {};
|
|
57709
|
+
if (Array.isArray(tagsInput)) {
|
|
57710
|
+
for (const entry of tagsInput) {
|
|
57711
|
+
const e = entry;
|
|
57712
|
+
const k = e["Key"];
|
|
57713
|
+
const v = e["Value"];
|
|
57714
|
+
if (typeof k === "string")
|
|
57715
|
+
out[k] = typeof v === "string" ? v : "";
|
|
57716
|
+
}
|
|
57717
|
+
return out;
|
|
57718
|
+
}
|
|
57719
|
+
if (typeof tagsInput === "object" && tagsInput !== null) {
|
|
57720
|
+
for (const [k, v] of Object.entries(tagsInput)) {
|
|
57721
|
+
out[k] = typeof v === "string" ? v : "";
|
|
57722
|
+
}
|
|
57723
|
+
return out;
|
|
57724
|
+
}
|
|
57725
|
+
return out;
|
|
57726
|
+
}
|
|
57727
|
+
function pickDefined(obj) {
|
|
57728
|
+
const out = {};
|
|
57729
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
57730
|
+
if (v === void 0 || v === null)
|
|
57731
|
+
continue;
|
|
57732
|
+
if (typeof v === "object" && !Array.isArray(v)) {
|
|
57733
|
+
const inner = pickDefined(v);
|
|
57734
|
+
out[k] = inner;
|
|
57735
|
+
} else {
|
|
57736
|
+
out[k] = v;
|
|
57737
|
+
}
|
|
57738
|
+
}
|
|
57739
|
+
return out;
|
|
57740
|
+
}
|
|
57741
|
+
var GlueCrawlerProvider = class {
|
|
57742
|
+
client;
|
|
57743
|
+
stsClient;
|
|
57744
|
+
cachedAccountId;
|
|
57745
|
+
providerRegion = process.env["AWS_REGION"];
|
|
57746
|
+
logger = getLogger().child("GlueCrawlerProvider");
|
|
57747
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
57748
|
+
[
|
|
57749
|
+
"AWS::Glue::Crawler",
|
|
57750
|
+
/* @__PURE__ */ new Set([
|
|
57751
|
+
"Name",
|
|
57752
|
+
"Role",
|
|
57753
|
+
"Targets",
|
|
57754
|
+
"DatabaseName",
|
|
57755
|
+
"Description",
|
|
57756
|
+
"Schedule",
|
|
57757
|
+
"Classifiers",
|
|
57758
|
+
"TablePrefix",
|
|
57759
|
+
"SchemaChangePolicy",
|
|
57760
|
+
"RecrawlPolicy",
|
|
57761
|
+
"LineageConfiguration",
|
|
57762
|
+
"LakeFormationConfiguration",
|
|
57763
|
+
"Configuration",
|
|
57764
|
+
"CrawlerSecurityConfiguration",
|
|
57765
|
+
"Tags"
|
|
57766
|
+
])
|
|
57767
|
+
]
|
|
57768
|
+
]);
|
|
57769
|
+
getClient() {
|
|
57770
|
+
if (!this.client) {
|
|
57771
|
+
this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
57772
|
+
}
|
|
57773
|
+
return this.client;
|
|
57774
|
+
}
|
|
57775
|
+
getStsClient() {
|
|
57776
|
+
if (!this.stsClient) {
|
|
57777
|
+
this.stsClient = new STSClient8(this.providerRegion ? { region: this.providerRegion } : {});
|
|
57778
|
+
}
|
|
57779
|
+
return this.stsClient;
|
|
57780
|
+
}
|
|
57781
|
+
async create(logicalId, resourceType, properties) {
|
|
57782
|
+
this.logger.debug(`Creating Glue Crawler ${logicalId}`);
|
|
57783
|
+
const name = properties["Name"] ?? logicalId;
|
|
57784
|
+
const role = properties["Role"];
|
|
57785
|
+
const targets = properties["Targets"];
|
|
57786
|
+
if (!role) {
|
|
57787
|
+
throw new ProvisioningError(
|
|
57788
|
+
`Role is required for Glue Crawler ${logicalId}`,
|
|
57789
|
+
resourceType,
|
|
57790
|
+
logicalId
|
|
57791
|
+
);
|
|
57792
|
+
}
|
|
57793
|
+
if (!targets) {
|
|
57794
|
+
throw new ProvisioningError(
|
|
57795
|
+
`Targets is required for Glue Crawler ${logicalId}`,
|
|
57796
|
+
resourceType,
|
|
57797
|
+
logicalId
|
|
57798
|
+
);
|
|
57799
|
+
}
|
|
57800
|
+
try {
|
|
57801
|
+
const tags = cfnTagsToMap(properties["Tags"]);
|
|
57802
|
+
await this.getClient().send(
|
|
57803
|
+
new CreateCrawlerCommand({
|
|
57804
|
+
Name: name,
|
|
57805
|
+
Role: role,
|
|
57806
|
+
Targets: targets,
|
|
57807
|
+
...buildCrawlerCommonFields(properties),
|
|
57808
|
+
...tags && { Tags: tags }
|
|
57809
|
+
})
|
|
57810
|
+
);
|
|
57811
|
+
this.logger.debug(`Successfully created Glue Crawler ${logicalId}: ${name}`);
|
|
57812
|
+
return { physicalId: name, attributes: {} };
|
|
57813
|
+
} catch (error) {
|
|
57814
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57815
|
+
throw new ProvisioningError(
|
|
57816
|
+
`Failed to create Glue Crawler ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57817
|
+
resourceType,
|
|
57818
|
+
logicalId,
|
|
57819
|
+
void 0,
|
|
57820
|
+
cause
|
|
57821
|
+
);
|
|
57822
|
+
}
|
|
57823
|
+
}
|
|
57824
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
57825
|
+
this.logger.debug(`Updating Glue Crawler ${logicalId}: ${physicalId}`);
|
|
57826
|
+
try {
|
|
57827
|
+
await this.getClient().send(
|
|
57828
|
+
new UpdateCrawlerCommand({
|
|
57829
|
+
Name: physicalId,
|
|
57830
|
+
...properties["Role"] !== void 0 && { Role: properties["Role"] },
|
|
57831
|
+
...properties["Targets"] !== void 0 && {
|
|
57832
|
+
Targets: properties["Targets"]
|
|
57833
|
+
},
|
|
57834
|
+
...buildCrawlerCommonFields(properties)
|
|
57835
|
+
})
|
|
57836
|
+
);
|
|
57837
|
+
const oldTags = cfnTagsToMap(previousProperties["Tags"]) ?? {};
|
|
57838
|
+
const newTags = cfnTagsToMap(properties["Tags"]) ?? {};
|
|
57839
|
+
await this.applyTagDiff(physicalId, oldTags, newTags);
|
|
57840
|
+
return { physicalId, wasReplaced: false };
|
|
57841
|
+
} catch (error) {
|
|
57842
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57843
|
+
throw new ProvisioningError(
|
|
57844
|
+
`Failed to update Glue Crawler ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57845
|
+
resourceType,
|
|
57846
|
+
logicalId,
|
|
57847
|
+
physicalId,
|
|
57848
|
+
cause
|
|
57849
|
+
);
|
|
57850
|
+
}
|
|
57851
|
+
}
|
|
57852
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
57853
|
+
this.logger.debug(`Deleting Glue Crawler ${logicalId}: ${physicalId}`);
|
|
57854
|
+
try {
|
|
57855
|
+
await this.getClient().send(new DeleteCrawlerCommand({ Name: physicalId }));
|
|
57856
|
+
} catch (error) {
|
|
57857
|
+
if (error instanceof EntityNotFoundException) {
|
|
57858
|
+
const clientRegion = await this.getClient().config.region();
|
|
57859
|
+
assertRegionMatch(
|
|
57860
|
+
clientRegion,
|
|
57861
|
+
context?.expectedRegion,
|
|
57862
|
+
resourceType,
|
|
57863
|
+
logicalId,
|
|
57864
|
+
physicalId
|
|
57865
|
+
);
|
|
57866
|
+
this.logger.debug(`Glue Crawler ${physicalId} does not exist, skipping deletion`);
|
|
57867
|
+
return;
|
|
57868
|
+
}
|
|
57869
|
+
const cause = error instanceof Error ? error : void 0;
|
|
57870
|
+
throw new ProvisioningError(
|
|
57871
|
+
`Failed to delete Glue Crawler ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
57872
|
+
resourceType,
|
|
57873
|
+
logicalId,
|
|
57874
|
+
physicalId,
|
|
57875
|
+
cause
|
|
57876
|
+
);
|
|
57877
|
+
}
|
|
57878
|
+
}
|
|
57879
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- explicit-override-only intentionally has no AWS calls
|
|
57880
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
57881
|
+
if (attributeName === "Id" || attributeName === "Ref" || attributeName === "Name") {
|
|
57882
|
+
return physicalId;
|
|
57883
|
+
}
|
|
57884
|
+
return void 0;
|
|
57885
|
+
}
|
|
57886
|
+
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
57887
|
+
let crawler;
|
|
57888
|
+
try {
|
|
57889
|
+
const resp = await this.getClient().send(new GetCrawlerCommand({ Name: physicalId }));
|
|
57890
|
+
crawler = resp.Crawler;
|
|
57891
|
+
} catch (err) {
|
|
57892
|
+
if (err instanceof EntityNotFoundException)
|
|
57893
|
+
return void 0;
|
|
57894
|
+
throw err;
|
|
57895
|
+
}
|
|
57896
|
+
if (!crawler)
|
|
57897
|
+
return void 0;
|
|
57898
|
+
const result = {
|
|
57899
|
+
Name: crawler.Name ?? physicalId,
|
|
57900
|
+
Role: crawler.Role ?? "",
|
|
57901
|
+
Targets: crawler.Targets ? pickDefined(crawler.Targets) : {},
|
|
57902
|
+
DatabaseName: crawler.DatabaseName ?? "",
|
|
57903
|
+
Description: crawler.Description ?? "",
|
|
57904
|
+
// CFn `Schedule` is the structured wrapper; reverse-map from the
|
|
57905
|
+
// SDK's `Schedule { ScheduleExpression, State }` Description shape.
|
|
57906
|
+
Schedule: crawler.Schedule?.ScheduleExpression ? { ScheduleExpression: crawler.Schedule.ScheduleExpression } : {},
|
|
57907
|
+
Classifiers: crawler.Classifiers ?? [],
|
|
57908
|
+
TablePrefix: crawler.TablePrefix ?? "",
|
|
57909
|
+
SchemaChangePolicy: crawler.SchemaChangePolicy ? pickDefined(crawler.SchemaChangePolicy) : {},
|
|
57910
|
+
RecrawlPolicy: crawler.RecrawlPolicy ? pickDefined(crawler.RecrawlPolicy) : {},
|
|
57911
|
+
LineageConfiguration: crawler.LineageConfiguration ? pickDefined(crawler.LineageConfiguration) : {},
|
|
57912
|
+
LakeFormationConfiguration: crawler.LakeFormationConfiguration ? pickDefined(crawler.LakeFormationConfiguration) : {},
|
|
57913
|
+
Configuration: crawler.Configuration ?? "",
|
|
57914
|
+
CrawlerSecurityConfiguration: crawler.CrawlerSecurityConfiguration ?? ""
|
|
57915
|
+
};
|
|
57916
|
+
result["Tags"] = await fetchGlueTags(
|
|
57917
|
+
this.getClient(),
|
|
57918
|
+
this.getStsClient(),
|
|
57919
|
+
"crawler",
|
|
57920
|
+
crawler.Name ?? physicalId,
|
|
57921
|
+
this.cachedAccountId,
|
|
57922
|
+
this.logger
|
|
57923
|
+
);
|
|
57924
|
+
return result;
|
|
57925
|
+
}
|
|
57926
|
+
/**
|
|
57927
|
+
* Start (or stop) a crawler's schedule. Exposed for downstream tooling
|
|
57928
|
+
* — not part of `update()` because AWS treats schedule activation as a
|
|
57929
|
+
* separate side-effect from crawler config update.
|
|
57930
|
+
*/
|
|
57931
|
+
async startSchedule(physicalId) {
|
|
57932
|
+
await this.getClient().send(new StartCrawlerScheduleCommand({ CrawlerName: physicalId }));
|
|
57933
|
+
}
|
|
57934
|
+
async stopSchedule(physicalId) {
|
|
57935
|
+
await this.getClient().send(new StopCrawlerScheduleCommand({ CrawlerName: physicalId }));
|
|
57936
|
+
}
|
|
57937
|
+
async applyTagDiff(physicalId, oldTags, newTags) {
|
|
57938
|
+
const arn = await buildGlueResourceArn(
|
|
57939
|
+
this.getClient(),
|
|
57940
|
+
this.getStsClient(),
|
|
57941
|
+
"crawler",
|
|
57942
|
+
physicalId,
|
|
57943
|
+
this.cachedAccountId
|
|
57944
|
+
);
|
|
57945
|
+
const toAdd = {};
|
|
57946
|
+
const toRemove = [];
|
|
57947
|
+
for (const [k, v] of Object.entries(newTags)) {
|
|
57948
|
+
if (oldTags[k] !== v)
|
|
57949
|
+
toAdd[k] = v;
|
|
57950
|
+
}
|
|
57951
|
+
for (const k of Object.keys(oldTags)) {
|
|
57952
|
+
if (!(k in newTags))
|
|
57953
|
+
toRemove.push(k);
|
|
57954
|
+
}
|
|
57955
|
+
if (Object.keys(toAdd).length > 0 || toRemove.length > 0) {
|
|
57956
|
+
const { TagResourceCommand: TagResourceCommand17, UntagResourceCommand: UntagResourceCommand16 } = await import("@aws-sdk/client-glue");
|
|
57957
|
+
if (Object.keys(toAdd).length > 0) {
|
|
57958
|
+
await this.getClient().send(new TagResourceCommand17({ ResourceArn: arn, TagsToAdd: toAdd }));
|
|
57959
|
+
}
|
|
57960
|
+
if (toRemove.length > 0) {
|
|
57961
|
+
await this.getClient().send(
|
|
57962
|
+
new UntagResourceCommand16({ ResourceArn: arn, TagsToRemove: toRemove })
|
|
57963
|
+
);
|
|
57964
|
+
}
|
|
57965
|
+
}
|
|
57966
|
+
}
|
|
57967
|
+
async import(input) {
|
|
57968
|
+
const explicitName = input.knownPhysicalId ?? input.properties["Name"];
|
|
57969
|
+
if (!explicitName)
|
|
57970
|
+
return null;
|
|
57971
|
+
try {
|
|
57972
|
+
await this.getClient().send(new GetCrawlerCommand({ Name: explicitName }));
|
|
57973
|
+
return { physicalId: explicitName, attributes: {} };
|
|
57974
|
+
} catch (err) {
|
|
57975
|
+
if (err instanceof EntityNotFoundException)
|
|
57976
|
+
return null;
|
|
57977
|
+
throw err;
|
|
57978
|
+
}
|
|
57979
|
+
}
|
|
57980
|
+
};
|
|
57981
|
+
function buildCrawlerCommonFields(p) {
|
|
57982
|
+
const r = {};
|
|
57983
|
+
if (p["DatabaseName"] !== void 0)
|
|
57984
|
+
r["DatabaseName"] = p["DatabaseName"];
|
|
57985
|
+
if (p["Description"] !== void 0)
|
|
57986
|
+
r["Description"] = p["Description"];
|
|
57987
|
+
if (p["Classifiers"] !== void 0)
|
|
57988
|
+
r["Classifiers"] = p["Classifiers"];
|
|
57989
|
+
if (p["TablePrefix"] !== void 0)
|
|
57990
|
+
r["TablePrefix"] = p["TablePrefix"];
|
|
57991
|
+
if (p["Schedule"] !== void 0) {
|
|
57992
|
+
const sched = p["Schedule"];
|
|
57993
|
+
if (typeof sched === "string") {
|
|
57994
|
+
r["Schedule"] = sched;
|
|
57995
|
+
} else if (typeof sched === "object" && sched !== null) {
|
|
57996
|
+
const wrap = sched;
|
|
57997
|
+
if (wrap["ScheduleExpression"] !== void 0) {
|
|
57998
|
+
r["Schedule"] = wrap["ScheduleExpression"];
|
|
57999
|
+
}
|
|
58000
|
+
}
|
|
58001
|
+
}
|
|
58002
|
+
if (p["SchemaChangePolicy"] !== void 0) {
|
|
58003
|
+
r["SchemaChangePolicy"] = p["SchemaChangePolicy"];
|
|
58004
|
+
}
|
|
58005
|
+
if (p["RecrawlPolicy"] !== void 0) {
|
|
58006
|
+
r["RecrawlPolicy"] = p["RecrawlPolicy"];
|
|
58007
|
+
}
|
|
58008
|
+
if (p["LineageConfiguration"] !== void 0) {
|
|
58009
|
+
r["LineageConfiguration"] = p["LineageConfiguration"];
|
|
58010
|
+
}
|
|
58011
|
+
if (p["LakeFormationConfiguration"] !== void 0) {
|
|
58012
|
+
r["LakeFormationConfiguration"] = p["LakeFormationConfiguration"];
|
|
58013
|
+
}
|
|
58014
|
+
if (p["Configuration"] !== void 0)
|
|
58015
|
+
r["Configuration"] = p["Configuration"];
|
|
58016
|
+
if (p["CrawlerSecurityConfiguration"] !== void 0) {
|
|
58017
|
+
r["CrawlerSecurityConfiguration"] = p["CrawlerSecurityConfiguration"];
|
|
58018
|
+
}
|
|
58019
|
+
return r;
|
|
58020
|
+
}
|
|
58021
|
+
var GlueConnectionProvider = class {
|
|
58022
|
+
client;
|
|
58023
|
+
providerRegion = process.env["AWS_REGION"];
|
|
58024
|
+
logger = getLogger().child("GlueConnectionProvider");
|
|
58025
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
58026
|
+
["AWS::Glue::Connection", /* @__PURE__ */ new Set(["ConnectionInput", "CatalogId"])]
|
|
58027
|
+
]);
|
|
58028
|
+
getClient() {
|
|
58029
|
+
if (!this.client) {
|
|
58030
|
+
this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
58031
|
+
}
|
|
58032
|
+
return this.client;
|
|
58033
|
+
}
|
|
58034
|
+
async create(logicalId, resourceType, properties) {
|
|
58035
|
+
this.logger.debug(`Creating Glue Connection ${logicalId}`);
|
|
58036
|
+
const connectionInput = properties["ConnectionInput"];
|
|
58037
|
+
if (!connectionInput) {
|
|
58038
|
+
throw new ProvisioningError(
|
|
58039
|
+
`ConnectionInput is required for Glue Connection ${logicalId}`,
|
|
58040
|
+
resourceType,
|
|
58041
|
+
logicalId
|
|
58042
|
+
);
|
|
58043
|
+
}
|
|
58044
|
+
const name = connectionInput["Name"] ?? logicalId;
|
|
58045
|
+
const catalogId = properties["CatalogId"];
|
|
58046
|
+
try {
|
|
58047
|
+
await this.getClient().send(
|
|
58048
|
+
new CreateConnectionCommand({
|
|
58049
|
+
...catalogId && { CatalogId: catalogId },
|
|
58050
|
+
ConnectionInput: buildConnectionInput(connectionInput, name)
|
|
58051
|
+
})
|
|
58052
|
+
);
|
|
58053
|
+
this.logger.debug(`Successfully created Glue Connection ${logicalId}: ${name}`);
|
|
58054
|
+
return { physicalId: name, attributes: {} };
|
|
58055
|
+
} catch (error) {
|
|
58056
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58057
|
+
throw new ProvisioningError(
|
|
58058
|
+
`Failed to create Glue Connection ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58059
|
+
resourceType,
|
|
58060
|
+
logicalId,
|
|
58061
|
+
void 0,
|
|
58062
|
+
cause
|
|
58063
|
+
);
|
|
58064
|
+
}
|
|
58065
|
+
}
|
|
58066
|
+
async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
58067
|
+
this.logger.debug(`Updating Glue Connection ${logicalId}: ${physicalId}`);
|
|
58068
|
+
const connectionInput = properties["ConnectionInput"];
|
|
58069
|
+
if (!connectionInput) {
|
|
58070
|
+
throw new ProvisioningError(
|
|
58071
|
+
`ConnectionInput is required for Glue Connection update ${logicalId}`,
|
|
58072
|
+
resourceType,
|
|
58073
|
+
logicalId,
|
|
58074
|
+
physicalId
|
|
58075
|
+
);
|
|
58076
|
+
}
|
|
58077
|
+
const catalogId = properties["CatalogId"];
|
|
58078
|
+
try {
|
|
58079
|
+
await this.getClient().send(
|
|
58080
|
+
new UpdateConnectionCommand({
|
|
58081
|
+
...catalogId && { CatalogId: catalogId },
|
|
58082
|
+
Name: physicalId,
|
|
58083
|
+
ConnectionInput: buildConnectionInput(connectionInput, physicalId)
|
|
58084
|
+
})
|
|
58085
|
+
);
|
|
58086
|
+
return { physicalId, wasReplaced: false };
|
|
58087
|
+
} catch (error) {
|
|
58088
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58089
|
+
throw new ProvisioningError(
|
|
58090
|
+
`Failed to update Glue Connection ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58091
|
+
resourceType,
|
|
58092
|
+
logicalId,
|
|
58093
|
+
physicalId,
|
|
58094
|
+
cause
|
|
58095
|
+
);
|
|
58096
|
+
}
|
|
58097
|
+
}
|
|
58098
|
+
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
58099
|
+
this.logger.debug(`Deleting Glue Connection ${logicalId}: ${physicalId}`);
|
|
58100
|
+
const catalogId = properties?.["CatalogId"];
|
|
58101
|
+
try {
|
|
58102
|
+
await this.getClient().send(
|
|
58103
|
+
new DeleteConnectionCommand({
|
|
58104
|
+
ConnectionName: physicalId,
|
|
58105
|
+
...catalogId && { CatalogId: catalogId }
|
|
58106
|
+
})
|
|
58107
|
+
);
|
|
58108
|
+
} catch (error) {
|
|
58109
|
+
if (error instanceof EntityNotFoundException) {
|
|
58110
|
+
const clientRegion = await this.getClient().config.region();
|
|
58111
|
+
assertRegionMatch(
|
|
58112
|
+
clientRegion,
|
|
58113
|
+
context?.expectedRegion,
|
|
58114
|
+
resourceType,
|
|
58115
|
+
logicalId,
|
|
58116
|
+
physicalId
|
|
58117
|
+
);
|
|
58118
|
+
this.logger.debug(`Glue Connection ${physicalId} does not exist, skipping deletion`);
|
|
58119
|
+
return;
|
|
58120
|
+
}
|
|
58121
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58122
|
+
throw new ProvisioningError(
|
|
58123
|
+
`Failed to delete Glue Connection ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58124
|
+
resourceType,
|
|
58125
|
+
logicalId,
|
|
58126
|
+
physicalId,
|
|
58127
|
+
cause
|
|
58128
|
+
);
|
|
58129
|
+
}
|
|
58130
|
+
}
|
|
58131
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- explicit-override-only intentionally has no AWS calls
|
|
58132
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
58133
|
+
if (attributeName === "Id" || attributeName === "Ref" || attributeName === "Name") {
|
|
58134
|
+
return physicalId;
|
|
58135
|
+
}
|
|
58136
|
+
return void 0;
|
|
58137
|
+
}
|
|
58138
|
+
async readCurrentState(physicalId, _logicalId, _resourceType, properties) {
|
|
58139
|
+
const catalogId = properties?.["CatalogId"];
|
|
58140
|
+
let conn;
|
|
58141
|
+
try {
|
|
58142
|
+
const resp = await this.getClient().send(
|
|
58143
|
+
new GetConnectionCommand({ Name: physicalId, ...catalogId && { CatalogId: catalogId } })
|
|
58144
|
+
);
|
|
58145
|
+
conn = resp.Connection;
|
|
58146
|
+
} catch (err) {
|
|
58147
|
+
if (err instanceof EntityNotFoundException)
|
|
58148
|
+
return void 0;
|
|
58149
|
+
throw err;
|
|
58150
|
+
}
|
|
58151
|
+
if (!conn)
|
|
58152
|
+
return void 0;
|
|
58153
|
+
const ci = {
|
|
58154
|
+
Name: conn.Name ?? physicalId,
|
|
58155
|
+
ConnectionType: conn.ConnectionType ?? "",
|
|
58156
|
+
Description: conn.Description ?? "",
|
|
58157
|
+
MatchCriteria: conn.MatchCriteria ?? [],
|
|
58158
|
+
ConnectionProperties: conn.ConnectionProperties ?? {},
|
|
58159
|
+
SparkProperties: conn.SparkProperties ?? {},
|
|
58160
|
+
AthenaProperties: conn.AthenaProperties ?? {},
|
|
58161
|
+
PythonProperties: conn.PythonProperties ?? {},
|
|
58162
|
+
PhysicalConnectionRequirements: conn.PhysicalConnectionRequirements ? pickDefined(conn.PhysicalConnectionRequirements) : {}
|
|
58163
|
+
};
|
|
58164
|
+
return { ConnectionInput: ci };
|
|
58165
|
+
}
|
|
58166
|
+
async import(input) {
|
|
58167
|
+
const explicitName = input.knownPhysicalId ?? input.properties["ConnectionInput"]?.["Name"];
|
|
58168
|
+
if (!explicitName)
|
|
58169
|
+
return null;
|
|
58170
|
+
const catalogId = input.properties["CatalogId"];
|
|
58171
|
+
try {
|
|
58172
|
+
await this.getClient().send(
|
|
58173
|
+
new GetConnectionCommand({
|
|
58174
|
+
Name: explicitName,
|
|
58175
|
+
...catalogId && { CatalogId: catalogId }
|
|
58176
|
+
})
|
|
58177
|
+
);
|
|
58178
|
+
return { physicalId: explicitName, attributes: {} };
|
|
58179
|
+
} catch (err) {
|
|
58180
|
+
if (err instanceof EntityNotFoundException)
|
|
58181
|
+
return null;
|
|
58182
|
+
throw err;
|
|
58183
|
+
}
|
|
58184
|
+
}
|
|
58185
|
+
};
|
|
58186
|
+
function buildConnectionInput(ci, fallbackName) {
|
|
58187
|
+
const result = {
|
|
58188
|
+
Name: ci["Name"] ?? fallbackName,
|
|
58189
|
+
ConnectionType: ci["ConnectionType"],
|
|
58190
|
+
ConnectionProperties: ci["ConnectionProperties"] ?? {}
|
|
58191
|
+
};
|
|
58192
|
+
if (ci["Description"] !== void 0)
|
|
58193
|
+
result.Description = ci["Description"];
|
|
58194
|
+
if (ci["MatchCriteria"] !== void 0)
|
|
58195
|
+
result.MatchCriteria = ci["MatchCriteria"];
|
|
58196
|
+
if (ci["SparkProperties"] !== void 0) {
|
|
58197
|
+
result.SparkProperties = ci["SparkProperties"];
|
|
58198
|
+
}
|
|
58199
|
+
if (ci["AthenaProperties"] !== void 0) {
|
|
58200
|
+
result.AthenaProperties = ci["AthenaProperties"];
|
|
58201
|
+
}
|
|
58202
|
+
if (ci["PythonProperties"] !== void 0) {
|
|
58203
|
+
result.PythonProperties = ci["PythonProperties"];
|
|
58204
|
+
}
|
|
58205
|
+
if (ci["PhysicalConnectionRequirements"] !== void 0) {
|
|
58206
|
+
result.PhysicalConnectionRequirements = ci["PhysicalConnectionRequirements"];
|
|
58207
|
+
}
|
|
58208
|
+
if (ci["AuthenticationConfiguration"] !== void 0) {
|
|
58209
|
+
result.AuthenticationConfiguration = ci["AuthenticationConfiguration"];
|
|
58210
|
+
}
|
|
58211
|
+
if (ci["ValidateCredentials"] !== void 0) {
|
|
58212
|
+
result.ValidateCredentials = ci["ValidateCredentials"];
|
|
58213
|
+
}
|
|
58214
|
+
if (ci["ValidateForComputeEnvironments"] !== void 0) {
|
|
58215
|
+
result.ValidateForComputeEnvironments = ci["ValidateForComputeEnvironments"];
|
|
58216
|
+
}
|
|
58217
|
+
return result;
|
|
58218
|
+
}
|
|
58219
|
+
var GlueTriggerProvider = class {
|
|
58220
|
+
client;
|
|
58221
|
+
stsClient;
|
|
58222
|
+
cachedAccountId;
|
|
58223
|
+
providerRegion = process.env["AWS_REGION"];
|
|
58224
|
+
logger = getLogger().child("GlueTriggerProvider");
|
|
58225
|
+
handledProperties = /* @__PURE__ */ new Map([
|
|
58226
|
+
[
|
|
58227
|
+
"AWS::Glue::Trigger",
|
|
58228
|
+
/* @__PURE__ */ new Set([
|
|
58229
|
+
"Name",
|
|
58230
|
+
"Type",
|
|
58231
|
+
"Schedule",
|
|
58232
|
+
"Actions",
|
|
58233
|
+
"Predicate",
|
|
58234
|
+
"Description",
|
|
58235
|
+
"StartOnCreation",
|
|
58236
|
+
"EventBatchingCondition",
|
|
58237
|
+
"WorkflowName",
|
|
58238
|
+
"Tags"
|
|
58239
|
+
])
|
|
58240
|
+
]
|
|
58241
|
+
]);
|
|
58242
|
+
getClient() {
|
|
58243
|
+
if (!this.client) {
|
|
58244
|
+
this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
58245
|
+
}
|
|
58246
|
+
return this.client;
|
|
58247
|
+
}
|
|
58248
|
+
getStsClient() {
|
|
58249
|
+
if (!this.stsClient) {
|
|
58250
|
+
this.stsClient = new STSClient8(this.providerRegion ? { region: this.providerRegion } : {});
|
|
58251
|
+
}
|
|
58252
|
+
return this.stsClient;
|
|
58253
|
+
}
|
|
58254
|
+
async create(logicalId, resourceType, properties) {
|
|
58255
|
+
this.logger.debug(`Creating Glue Trigger ${logicalId}`);
|
|
58256
|
+
const name = properties["Name"] ?? logicalId;
|
|
58257
|
+
const type = properties["Type"];
|
|
58258
|
+
const actions = properties["Actions"];
|
|
58259
|
+
if (!type) {
|
|
58260
|
+
throw new ProvisioningError(
|
|
58261
|
+
`Type is required for Glue Trigger ${logicalId}`,
|
|
58262
|
+
resourceType,
|
|
58263
|
+
logicalId
|
|
58264
|
+
);
|
|
58265
|
+
}
|
|
58266
|
+
if (!actions) {
|
|
58267
|
+
throw new ProvisioningError(
|
|
58268
|
+
`Actions is required for Glue Trigger ${logicalId}`,
|
|
58269
|
+
resourceType,
|
|
58270
|
+
logicalId
|
|
58271
|
+
);
|
|
58272
|
+
}
|
|
58273
|
+
try {
|
|
58274
|
+
const tags = cfnTagsToMap(properties["Tags"]);
|
|
58275
|
+
await this.getClient().send(
|
|
58276
|
+
new CreateTriggerCommand({
|
|
58277
|
+
Name: name,
|
|
58278
|
+
Type: type,
|
|
58279
|
+
Actions: actions,
|
|
58280
|
+
...properties["Schedule"] !== void 0 && {
|
|
58281
|
+
Schedule: properties["Schedule"]
|
|
58282
|
+
},
|
|
58283
|
+
...properties["Predicate"] !== void 0 && {
|
|
58284
|
+
Predicate: properties["Predicate"]
|
|
58285
|
+
},
|
|
58286
|
+
...properties["Description"] !== void 0 && {
|
|
58287
|
+
Description: properties["Description"]
|
|
58288
|
+
},
|
|
58289
|
+
...properties["StartOnCreation"] !== void 0 && {
|
|
58290
|
+
StartOnCreation: properties["StartOnCreation"]
|
|
58291
|
+
},
|
|
58292
|
+
...properties["WorkflowName"] !== void 0 && {
|
|
58293
|
+
WorkflowName: properties["WorkflowName"]
|
|
58294
|
+
},
|
|
58295
|
+
...properties["EventBatchingCondition"] !== void 0 && {
|
|
58296
|
+
EventBatchingCondition: properties["EventBatchingCondition"]
|
|
58297
|
+
},
|
|
58298
|
+
...tags && { Tags: tags }
|
|
58299
|
+
})
|
|
58300
|
+
);
|
|
58301
|
+
this.logger.debug(`Successfully created Glue Trigger ${logicalId}: ${name}`);
|
|
58302
|
+
return { physicalId: name, attributes: {} };
|
|
58303
|
+
} catch (error) {
|
|
58304
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58305
|
+
throw new ProvisioningError(
|
|
58306
|
+
`Failed to create Glue Trigger ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58307
|
+
resourceType,
|
|
58308
|
+
logicalId,
|
|
58309
|
+
void 0,
|
|
58310
|
+
cause
|
|
58311
|
+
);
|
|
58312
|
+
}
|
|
58313
|
+
}
|
|
58314
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
58315
|
+
this.logger.debug(`Updating Glue Trigger ${logicalId}: ${physicalId}`);
|
|
58316
|
+
try {
|
|
58317
|
+
let restart = false;
|
|
58318
|
+
try {
|
|
58319
|
+
const cur = await this.getClient().send(new GetTriggerCommand({ Name: physicalId }));
|
|
58320
|
+
if (cur.Trigger?.State === "ACTIVATED") {
|
|
58321
|
+
restart = true;
|
|
58322
|
+
await this.getClient().send(new StopTriggerCommand({ Name: physicalId }));
|
|
58323
|
+
}
|
|
58324
|
+
} catch (err) {
|
|
58325
|
+
if (!(err instanceof EntityNotFoundException)) {
|
|
58326
|
+
this.logger.debug(
|
|
58327
|
+
`GetTrigger pre-check failed for ${physicalId}; continuing anyway: ${err instanceof Error ? err.message : String(err)}`
|
|
58328
|
+
);
|
|
58329
|
+
}
|
|
58330
|
+
}
|
|
58331
|
+
const update = {
|
|
58332
|
+
...properties["Description"] !== void 0 && {
|
|
58333
|
+
Description: properties["Description"]
|
|
58334
|
+
},
|
|
58335
|
+
...properties["Schedule"] !== void 0 && {
|
|
58336
|
+
Schedule: properties["Schedule"]
|
|
58337
|
+
},
|
|
58338
|
+
...properties["Actions"] !== void 0 && {
|
|
58339
|
+
Actions: properties["Actions"]
|
|
58340
|
+
},
|
|
58341
|
+
...properties["Predicate"] !== void 0 && {
|
|
58342
|
+
Predicate: properties["Predicate"]
|
|
58343
|
+
},
|
|
58344
|
+
...properties["EventBatchingCondition"] !== void 0 && {
|
|
58345
|
+
EventBatchingCondition: properties["EventBatchingCondition"]
|
|
58346
|
+
}
|
|
58347
|
+
};
|
|
58348
|
+
await this.getClient().send(
|
|
58349
|
+
new UpdateTriggerCommand({ Name: physicalId, TriggerUpdate: update })
|
|
58350
|
+
);
|
|
58351
|
+
if (restart) {
|
|
58352
|
+
await this.getClient().send(new StartTriggerCommand({ Name: physicalId }));
|
|
58353
|
+
}
|
|
58354
|
+
const oldTags = cfnTagsToMap(previousProperties["Tags"]) ?? {};
|
|
58355
|
+
const newTags = cfnTagsToMap(properties["Tags"]) ?? {};
|
|
58356
|
+
await this.applyTagDiff(physicalId, oldTags, newTags);
|
|
58357
|
+
return { physicalId, wasReplaced: false };
|
|
58358
|
+
} catch (error) {
|
|
58359
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58360
|
+
throw new ProvisioningError(
|
|
58361
|
+
`Failed to update Glue Trigger ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58362
|
+
resourceType,
|
|
58363
|
+
logicalId,
|
|
58364
|
+
physicalId,
|
|
58365
|
+
cause
|
|
58366
|
+
);
|
|
58367
|
+
}
|
|
58368
|
+
}
|
|
58369
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
58370
|
+
this.logger.debug(`Deleting Glue Trigger ${logicalId}: ${physicalId}`);
|
|
58371
|
+
try {
|
|
58372
|
+
await this.getClient().send(new DeleteTriggerCommand({ Name: physicalId }));
|
|
58373
|
+
} catch (error) {
|
|
58374
|
+
if (error instanceof EntityNotFoundException) {
|
|
58375
|
+
const clientRegion = await this.getClient().config.region();
|
|
58376
|
+
assertRegionMatch(
|
|
58377
|
+
clientRegion,
|
|
58378
|
+
context?.expectedRegion,
|
|
58379
|
+
resourceType,
|
|
58380
|
+
logicalId,
|
|
58381
|
+
physicalId
|
|
58382
|
+
);
|
|
58383
|
+
this.logger.debug(`Glue Trigger ${physicalId} does not exist, skipping deletion`);
|
|
58384
|
+
return;
|
|
58385
|
+
}
|
|
58386
|
+
const cause = error instanceof Error ? error : void 0;
|
|
58387
|
+
throw new ProvisioningError(
|
|
58388
|
+
`Failed to delete Glue Trigger ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58389
|
+
resourceType,
|
|
58390
|
+
logicalId,
|
|
58391
|
+
physicalId,
|
|
58392
|
+
cause
|
|
58393
|
+
);
|
|
58394
|
+
}
|
|
58395
|
+
}
|
|
58396
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- explicit-override-only intentionally has no AWS calls
|
|
58397
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
58398
|
+
if (attributeName === "Id" || attributeName === "Ref" || attributeName === "Name") {
|
|
58399
|
+
return physicalId;
|
|
58400
|
+
}
|
|
58401
|
+
return void 0;
|
|
58402
|
+
}
|
|
58403
|
+
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
58404
|
+
let trig;
|
|
58405
|
+
try {
|
|
58406
|
+
const resp = await this.getClient().send(new GetTriggerCommand({ Name: physicalId }));
|
|
58407
|
+
trig = resp.Trigger;
|
|
58408
|
+
} catch (err) {
|
|
58409
|
+
if (err instanceof EntityNotFoundException)
|
|
58410
|
+
return void 0;
|
|
58411
|
+
throw err;
|
|
58412
|
+
}
|
|
58413
|
+
if (!trig)
|
|
58414
|
+
return void 0;
|
|
58415
|
+
const result = {
|
|
58416
|
+
Name: trig.Name ?? physicalId,
|
|
58417
|
+
Type: trig.Type ?? "",
|
|
58418
|
+
Schedule: trig.Schedule ?? "",
|
|
58419
|
+
Description: trig.Description ?? "",
|
|
58420
|
+
WorkflowName: trig.WorkflowName ?? "",
|
|
58421
|
+
Actions: (trig.Actions ?? []).map(
|
|
58422
|
+
(a) => pickDefined(a)
|
|
58423
|
+
),
|
|
58424
|
+
Predicate: trig.Predicate ? {
|
|
58425
|
+
Logical: trig.Predicate.Logical ?? "",
|
|
58426
|
+
Conditions: (trig.Predicate.Conditions ?? []).map(
|
|
58427
|
+
(c) => pickDefined(c)
|
|
58428
|
+
)
|
|
58429
|
+
} : {},
|
|
58430
|
+
EventBatchingCondition: trig.EventBatchingCondition ? pickDefined(trig.EventBatchingCondition) : {}
|
|
58431
|
+
};
|
|
58432
|
+
result["Tags"] = await fetchGlueTags(
|
|
58433
|
+
this.getClient(),
|
|
58434
|
+
this.getStsClient(),
|
|
58435
|
+
"trigger",
|
|
58436
|
+
trig.Name ?? physicalId,
|
|
58437
|
+
this.cachedAccountId,
|
|
58438
|
+
this.logger
|
|
58439
|
+
);
|
|
58440
|
+
return result;
|
|
58441
|
+
}
|
|
58442
|
+
async applyTagDiff(physicalId, oldTags, newTags) {
|
|
58443
|
+
const arn = await buildGlueResourceArn(
|
|
58444
|
+
this.getClient(),
|
|
58445
|
+
this.getStsClient(),
|
|
58446
|
+
"trigger",
|
|
58447
|
+
physicalId,
|
|
58448
|
+
this.cachedAccountId
|
|
58449
|
+
);
|
|
58450
|
+
const toAdd = {};
|
|
58451
|
+
const toRemove = [];
|
|
58452
|
+
for (const [k, v] of Object.entries(newTags)) {
|
|
58453
|
+
if (oldTags[k] !== v)
|
|
58454
|
+
toAdd[k] = v;
|
|
58455
|
+
}
|
|
58456
|
+
for (const k of Object.keys(oldTags)) {
|
|
58457
|
+
if (!(k in newTags))
|
|
58458
|
+
toRemove.push(k);
|
|
58459
|
+
}
|
|
58460
|
+
if (Object.keys(toAdd).length > 0 || toRemove.length > 0) {
|
|
58461
|
+
const { TagResourceCommand: TagResourceCommand17, UntagResourceCommand: UntagResourceCommand16 } = await import("@aws-sdk/client-glue");
|
|
58462
|
+
if (Object.keys(toAdd).length > 0) {
|
|
58463
|
+
await this.getClient().send(new TagResourceCommand17({ ResourceArn: arn, TagsToAdd: toAdd }));
|
|
58464
|
+
}
|
|
58465
|
+
if (toRemove.length > 0) {
|
|
58466
|
+
await this.getClient().send(
|
|
58467
|
+
new UntagResourceCommand16({ ResourceArn: arn, TagsToRemove: toRemove })
|
|
58468
|
+
);
|
|
58469
|
+
}
|
|
58470
|
+
}
|
|
58471
|
+
}
|
|
58472
|
+
async import(input) {
|
|
58473
|
+
const explicitName = input.knownPhysicalId ?? input.properties["Name"];
|
|
58474
|
+
if (!explicitName)
|
|
58475
|
+
return null;
|
|
58476
|
+
try {
|
|
58477
|
+
await this.getClient().send(new GetTriggerCommand({ Name: explicitName }));
|
|
58478
|
+
return { physicalId: explicitName, attributes: {} };
|
|
58479
|
+
} catch (err) {
|
|
58480
|
+
if (err instanceof EntityNotFoundException)
|
|
58481
|
+
return null;
|
|
58482
|
+
throw err;
|
|
58483
|
+
}
|
|
58484
|
+
}
|
|
58485
|
+
};
|
|
57353
58486
|
|
|
57354
58487
|
// src/provisioning/providers/kms-provider.ts
|
|
57355
58488
|
import {
|
|
@@ -64033,6 +65166,10 @@ function registerAllProviders(registry) {
|
|
|
64033
65166
|
registry.register("AWS::Glue::Table", glueProvider);
|
|
64034
65167
|
registry.register("AWS::Glue::Workflow", new GlueWorkflowProvider());
|
|
64035
65168
|
registry.register("AWS::Glue::SecurityConfiguration", new GlueSecurityConfigurationProvider());
|
|
65169
|
+
registry.register("AWS::Glue::Job", new GlueJobProvider());
|
|
65170
|
+
registry.register("AWS::Glue::Crawler", new GlueCrawlerProvider());
|
|
65171
|
+
registry.register("AWS::Glue::Connection", new GlueConnectionProvider());
|
|
65172
|
+
registry.register("AWS::Glue::Trigger", new GlueTriggerProvider());
|
|
64036
65173
|
const kmsProvider = new KMSProvider();
|
|
64037
65174
|
registry.register("AWS::KMS::Key", kmsProvider);
|
|
64038
65175
|
registry.register("AWS::KMS::Alias", kmsProvider);
|
|
@@ -68853,7 +69990,7 @@ function reorderArgs(argv) {
|
|
|
68853
69990
|
}
|
|
68854
69991
|
async function main() {
|
|
68855
69992
|
const program = new Command14();
|
|
68856
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
69993
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.66.0");
|
|
68857
69994
|
program.addCommand(createBootstrapCommand());
|
|
68858
69995
|
program.addCommand(createSynthCommand());
|
|
68859
69996
|
program.addCommand(createListCommand());
|