@kensio/yulin 1.21.4 → 1.21.5
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/service/cloudformation/cdk/assets/sim-cdk-assets-publisher.d.ts +18 -13
- package/dist/service/cloudformation/cdk/assets/sim-cdk-assets-publisher.js +16 -24
- package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.d.ts +12 -0
- package/dist/service/cloudformation/cdk/sim-cdk-cloud-assembly.factory.js +16 -7
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.d.ts +3 -0
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.js +4 -1
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.d.ts +6 -0
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.js +7 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-deployer.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.d.ts +10 -0
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-options-deployed.js +14 -0
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.d.ts +11 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.js +3 -2
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.d.ts +5 -8
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.js +0 -14
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +9 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +2 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +10 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.js +1 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.d.ts +47 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-deploy-context.js +46 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +9 -19
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +12 -26
- package/dist/service/cloudformation/stack/sim-cfn-stack.js +2 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.type.d.ts +14 -0
- package/dist/service/s3/bucket/sim-s3-bucket-maker.d.ts +31 -0
- package/dist/service/s3/bucket/sim-s3-bucket-maker.js +41 -0
- package/dist/service/s3/command/create-bucket/create-bucket.handler.d.ts +2 -2
- package/dist/service/s3/command/create-bucket/create-bucket.handler.js +4 -12
- package/dist/service/s3/sim-s3-commands.d.ts +6 -0
- package/dist/service/s3/sim-s3-commands.js +7 -0
- package/dist/service/s3/sim-s3.d.ts +16 -0
- package/dist/service/s3/sim-s3.js +25 -0
- package/docs/services/cloudformation/README.md +56 -2
- package/package.json +2 -2
|
@@ -8,12 +8,16 @@ interface SimCdkAssetsPublisherProperties {
|
|
|
8
8
|
readonly stackName?: string | undefined;
|
|
9
9
|
readonly cdkOutContext?: SimCdkOutContext | undefined;
|
|
10
10
|
/**
|
|
11
|
-
* The principal the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* The principal the assets are published as.
|
|
12
|
+
*
|
|
13
|
+
* A real `cdk deploy` publishes assets before CloudFormation sees the
|
|
14
|
+
* template, as the file publishing Role the assets manifest names in each
|
|
15
|
+
* destination's `assumeRoleArn`. CloudFormation then processes the template
|
|
16
|
+
* as the execution Role. A deployment that names an assets caller is what
|
|
17
|
+
* tells the two apart here, and one that names none publishes as whoever
|
|
18
|
+
* deploys.
|
|
15
19
|
*/
|
|
16
|
-
readonly
|
|
20
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
17
21
|
}
|
|
18
22
|
/**
|
|
19
23
|
* Publishes a CDK cloud assembly's file assets into simulated S3.
|
|
@@ -25,7 +29,7 @@ interface SimCdkAssetsPublisherProperties {
|
|
|
25
29
|
* Lambda function resolves its code through the ordinary sim S3 fetch with no
|
|
26
30
|
* Lambda-specific asset handling.
|
|
27
31
|
*
|
|
28
|
-
* Publishing is byte movement only
|
|
32
|
+
* Publishing is byte movement only. Nothing here runs asset code. Functions
|
|
29
33
|
* sim Lambda cannot run, such as a CDK BucketDeployment provider written in
|
|
30
34
|
* Python, are declined later by the Lambda resource creator on their Runtime.
|
|
31
35
|
*/
|
|
@@ -42,15 +46,16 @@ export declare class SimCdkAssetsPublisher {
|
|
|
42
46
|
publish(): Promise<void>;
|
|
43
47
|
private publishAsset;
|
|
44
48
|
/**
|
|
45
|
-
*
|
|
49
|
+
* Make the staging Bucket if this is the first asset published into it,
|
|
46
50
|
* standing in for the CDK bootstrap stack that provisions it for real.
|
|
47
51
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
52
|
+
* The bootstrap stack runs long before the deployment, and neither the file
|
|
53
|
+
* publishing Role nor the execution Role creates this Bucket. It comes
|
|
54
|
+
* through `makeSimBucket` for that reason, which asks IAM nothing. A
|
|
55
|
+
* deployment scoped to the permissions its real execution Role holds would
|
|
56
|
+
* otherwise be refused `s3:CreateBucket` before creating a Resource.
|
|
57
|
+
*
|
|
58
|
+
* A name already taken in another scope is a real failure, and is reported.
|
|
54
59
|
*/
|
|
55
60
|
private ensureBucket;
|
|
56
61
|
private stagingS3;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SimCfnPseudoParameters } from "../../parameters/pseudo/sim-cfn-pseudo-parameters.js";
|
|
2
2
|
import { SimCdkAssetPublications, } from "./sim-cdk-asset-publications.js";
|
|
3
3
|
import { readSimCdkAssetBytes } from "./sim-cdk-asset-bytes.js";
|
|
4
|
-
import { simCfnResourceCallerOptions
|
|
4
|
+
import { simCfnResourceCallerOptions } from "../../resource/caller/sim-cfn-resource-caller-options.js";
|
|
5
5
|
/**
|
|
6
6
|
* Publishes a CDK cloud assembly's file assets into simulated S3.
|
|
7
7
|
*
|
|
@@ -12,7 +12,7 @@ import { simCfnResourceCallerOptions, } from "../../resource/caller/sim-cfn-reso
|
|
|
12
12
|
* Lambda function resolves its code through the ordinary sim S3 fetch with no
|
|
13
13
|
* Lambda-specific asset handling.
|
|
14
14
|
*
|
|
15
|
-
* Publishing is byte movement only
|
|
15
|
+
* Publishing is byte movement only. Nothing here runs asset code. Functions
|
|
16
16
|
* sim Lambda cannot run, such as a CDK BucketDeployment provider written in
|
|
17
17
|
* Python, are declined later by the Lambda resource creator on their Runtime.
|
|
18
18
|
*/
|
|
@@ -42,7 +42,7 @@ export class SimCdkAssetsPublisher {
|
|
|
42
42
|
}),
|
|
43
43
|
}).resolve(cdkOutContext.assetsManifest);
|
|
44
44
|
for (const publication of publications) {
|
|
45
|
-
// oxlint-disable-next-line no-await-in-loop --
|
|
45
|
+
// oxlint-disable-next-line no-await-in-loop -- published in manifest order, as cdk-assets publishes them
|
|
46
46
|
await this.publishAsset(publication);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -52,38 +52,30 @@ export class SimCdkAssetsPublisher {
|
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
const s3 = this.stagingS3();
|
|
55
|
-
|
|
56
|
-
await this.ensureBucket(s3, publication.bucketName, options);
|
|
55
|
+
this.ensureBucket(s3, publication.bucketName);
|
|
57
56
|
await s3.putObject({
|
|
58
57
|
input: {
|
|
59
58
|
Bucket: publication.bucketName,
|
|
60
59
|
Key: publication.objectKey,
|
|
61
60
|
Body: assetBytes,
|
|
62
61
|
},
|
|
63
|
-
},
|
|
62
|
+
}, simCfnResourceCallerOptions(this.properties.assetsCaller));
|
|
64
63
|
}
|
|
65
64
|
/**
|
|
66
|
-
*
|
|
65
|
+
* Make the staging Bucket if this is the first asset published into it,
|
|
67
66
|
* standing in for the CDK bootstrap stack that provisions it for real.
|
|
68
67
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
68
|
+
* The bootstrap stack runs long before the deployment, and neither the file
|
|
69
|
+
* publishing Role nor the execution Role creates this Bucket. It comes
|
|
70
|
+
* through `makeSimBucket` for that reason, which asks IAM nothing. A
|
|
71
|
+
* deployment scoped to the permissions its real execution Role holds would
|
|
72
|
+
* otherwise be refused `s3:CreateBucket` before creating a Resource.
|
|
73
|
+
*
|
|
74
|
+
* A name already taken in another scope is a real failure, and is reported.
|
|
75
75
|
*/
|
|
76
|
-
|
|
77
|
-
if (s3.getSimBucketByName(bucketName)
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
await s3.createBucket({ input: { Bucket: bucketName } }, options);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
if (s3.getSimBucketByName(bucketName) === undefined) {
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
76
|
+
ensureBucket(s3, bucketName) {
|
|
77
|
+
if (s3.getSimBucketByName(bucketName) === undefined) {
|
|
78
|
+
s3.makeSimBucket(bucketName);
|
|
87
79
|
}
|
|
88
80
|
}
|
|
89
81
|
stagingS3() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AsyncMappedFactory } from "@kensio/part-factory";
|
|
2
2
|
import { TemporaryDirectory } from "../../../util/filesystem/temporary-directory.js";
|
|
3
3
|
import type { SimCfnTemplateValueRecord } from "../template/value/sim-cfn-template-value.js";
|
|
4
|
+
import type { SimCdkAssetsManifest } from "./sim-cdk-out-context.js";
|
|
4
5
|
/**
|
|
5
6
|
* One synthesized Stack in a cloud assembly a test writes.
|
|
6
7
|
*/
|
|
@@ -25,9 +26,20 @@ export interface SimCdkCloudAssemblyStackInput {
|
|
|
25
26
|
readonly resources?: SimCfnTemplateValueRecord | undefined;
|
|
26
27
|
/** The template's Outputs, which a Stack sharing a value needs. */
|
|
27
28
|
readonly outputs?: SimCfnTemplateValueRecord | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The assets manifest `cdk synth` writes beside the template, for a Stack
|
|
31
|
+
* that stages file assets. A Stack given none has no manifest file at all,
|
|
32
|
+
* which is what a Stack with nothing to stage synthesizes.
|
|
33
|
+
*/
|
|
34
|
+
readonly assets?: SimCdkAssetsManifest | undefined;
|
|
28
35
|
}
|
|
29
36
|
export interface SimCdkCloudAssemblyInput {
|
|
30
37
|
readonly stacks: readonly SimCdkCloudAssemblyStackInput[];
|
|
38
|
+
/**
|
|
39
|
+
* Staged asset files to write into the assembly, keyed by the path an assets
|
|
40
|
+
* manifest source names.
|
|
41
|
+
*/
|
|
42
|
+
readonly assetFiles?: Record<string, string> | undefined;
|
|
31
43
|
}
|
|
32
44
|
/** The Bucket a Stack in a written assembly creates, unless it is given others. */
|
|
33
45
|
export declare function assemblyStackBucketName(artifactId: string): string;
|
|
@@ -23,13 +23,19 @@ export function assemblyStackBucketName(artifactId) {
|
|
|
23
23
|
export const simCdkCloudAssemblyFactory = new AsyncMappedFactory(() => ({ stacks: [{ artifactId: "SiteStack", regionName: "eu-west-2" }] }), async (input) => {
|
|
24
24
|
const directory = new TemporaryDirectory();
|
|
25
25
|
await directory.writeFile(["cdk.out", "manifest.json"], jsonStringify(assemblyManifest(input.stacks)));
|
|
26
|
-
await Promise.all(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
await Promise.all([
|
|
27
|
+
...input.stacks.map(async (stack) => directory.writeFile(["cdk.out", templateFileName(stack)],
|
|
28
|
+
// JSON.stringify drops an undefined value, so a Stack given no
|
|
29
|
+
// Outputs writes a template with none rather than a null one.
|
|
30
|
+
jsonStringify({
|
|
31
|
+
Resources: stackResources(stack),
|
|
32
|
+
Outputs: stack.outputs,
|
|
33
|
+
}))),
|
|
34
|
+
...input.stacks
|
|
35
|
+
.filter((stack) => stack.assets !== undefined)
|
|
36
|
+
.map(async (stack) => directory.writeFile(["cdk.out", assetsFileName(stack)], jsonStringify(stack.assets))),
|
|
37
|
+
...Object.entries(input.assetFiles ?? {}).map(async ([assetPath, content]) => directory.writeFile(["cdk.out", assetPath], content)),
|
|
38
|
+
]);
|
|
33
39
|
return directory;
|
|
34
40
|
});
|
|
35
41
|
function assemblyManifest(stacks) {
|
|
@@ -56,6 +62,9 @@ function assemblyManifest(stacks) {
|
|
|
56
62
|
function templateFileName(stack) {
|
|
57
63
|
return `${stack.artifactId}.template.json`;
|
|
58
64
|
}
|
|
65
|
+
function assetsFileName(stack) {
|
|
66
|
+
return `${stack.artifactId}.assets.json`;
|
|
67
|
+
}
|
|
59
68
|
function stackResources(stack) {
|
|
60
69
|
return (stack.resources ?? {
|
|
61
70
|
[`${stack.artifactId}Bucket`]: {
|
|
@@ -18,6 +18,8 @@ interface CreateStackCommandHandlerProperties {
|
|
|
18
18
|
readonly bindings?: readonly SimCfnBinding[] | undefined;
|
|
19
19
|
/** The principal the Stack's Resources are created as. */
|
|
20
20
|
readonly caller?: SimAwsCaller | undefined;
|
|
21
|
+
/** The principal the Stack's CDK file assets are published as. */
|
|
22
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
21
23
|
/** The order Resources with no dependency between them are started in. */
|
|
22
24
|
readonly resourceOrder?: SimCfnResourceOrder | undefined;
|
|
23
25
|
readonly exports?: SimCfnExports | undefined;
|
|
@@ -35,6 +37,7 @@ export declare class CreateStackCommandHandler implements CommandHandler<SimCrea
|
|
|
35
37
|
private readonly cdkOutContext;
|
|
36
38
|
private readonly bindings;
|
|
37
39
|
private readonly caller;
|
|
40
|
+
private readonly assetsCaller;
|
|
38
41
|
private readonly resourceOrder;
|
|
39
42
|
private readonly exports;
|
|
40
43
|
constructor(properties: CreateStackCommandHandlerProperties);
|
|
@@ -16,10 +16,11 @@ export class CreateStackCommandHandler {
|
|
|
16
16
|
cdkOutContext;
|
|
17
17
|
bindings;
|
|
18
18
|
caller;
|
|
19
|
+
assetsCaller;
|
|
19
20
|
resourceOrder;
|
|
20
21
|
exports;
|
|
21
22
|
constructor(properties) {
|
|
22
|
-
const { simAws, accountRegionScope, stacks, background, cdkOutContext, bindings, caller, resourceOrder, exports, } = properties;
|
|
23
|
+
const { simAws, accountRegionScope, stacks, background, cdkOutContext, bindings, caller, assetsCaller, resourceOrder, exports, } = properties;
|
|
23
24
|
this.simAws = simAws;
|
|
24
25
|
this.accountRegionScope = accountRegionScope;
|
|
25
26
|
this.stacks = stacks;
|
|
@@ -27,6 +28,7 @@ export class CreateStackCommandHandler {
|
|
|
27
28
|
this.cdkOutContext = cdkOutContext;
|
|
28
29
|
this.bindings = bindings;
|
|
29
30
|
this.caller = caller;
|
|
31
|
+
this.assetsCaller = assetsCaller;
|
|
30
32
|
this.resourceOrder = resourceOrder;
|
|
31
33
|
this.exports = exports;
|
|
32
34
|
}
|
|
@@ -65,6 +67,7 @@ export class CreateStackCommandHandler {
|
|
|
65
67
|
cdkOutContext: this.cdkOutContext,
|
|
66
68
|
bindings: this.bindings,
|
|
67
69
|
caller: this.caller,
|
|
70
|
+
assetsCaller: this.assetsCaller,
|
|
68
71
|
resourceOrder: this.resourceOrder,
|
|
69
72
|
exports: this.exports,
|
|
70
73
|
});
|
|
@@ -22,6 +22,11 @@ interface UpdateStackCommandHandlerProperties {
|
|
|
22
22
|
* one. Left out, the Stack goes on running as whoever deployed it.
|
|
23
23
|
*/
|
|
24
24
|
readonly caller?: SimAwsCaller | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The principal to publish the re-synthesized CDK file assets as, for an
|
|
27
|
+
* update that names one. Left out, they are published as `caller`.
|
|
28
|
+
*/
|
|
29
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
25
30
|
/** The export names published in this Account and Region. */
|
|
26
31
|
readonly exports?: SimCfnExports | undefined;
|
|
27
32
|
}
|
|
@@ -37,6 +42,7 @@ export declare class UpdateStackCommandHandler implements CommandHandler<SimUpda
|
|
|
37
42
|
private readonly background;
|
|
38
43
|
private readonly cdkOutContext;
|
|
39
44
|
private readonly caller;
|
|
45
|
+
private readonly assetsCaller;
|
|
40
46
|
private readonly exports;
|
|
41
47
|
constructor(properties: UpdateStackCommandHandlerProperties);
|
|
42
48
|
/**
|
|
@@ -14,6 +14,7 @@ export class UpdateStackCommandHandler {
|
|
|
14
14
|
background;
|
|
15
15
|
cdkOutContext;
|
|
16
16
|
caller;
|
|
17
|
+
assetsCaller;
|
|
17
18
|
exports;
|
|
18
19
|
constructor(properties) {
|
|
19
20
|
this.simAws = properties.simAws;
|
|
@@ -22,6 +23,7 @@ export class UpdateStackCommandHandler {
|
|
|
22
23
|
this.background = properties.background;
|
|
23
24
|
this.cdkOutContext = properties.cdkOutContext;
|
|
24
25
|
this.caller = properties.caller;
|
|
26
|
+
this.assetsCaller = properties.assetsCaller;
|
|
25
27
|
this.exports = properties.exports;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
@@ -51,7 +53,11 @@ export class UpdateStackCommandHandler {
|
|
|
51
53
|
stack,
|
|
52
54
|
input: command.input,
|
|
53
55
|
exports: this.exports,
|
|
54
|
-
}), {
|
|
56
|
+
}), {
|
|
57
|
+
cdkOutContext: this.cdkOutContext,
|
|
58
|
+
caller: this.caller,
|
|
59
|
+
assetsCaller: this.assetsCaller,
|
|
60
|
+
});
|
|
55
61
|
return {
|
|
56
62
|
StackId: stack.stackId,
|
|
57
63
|
$metadata: {},
|
|
@@ -27,7 +27,7 @@ export class SimCfnCdkOutDeployer {
|
|
|
27
27
|
}
|
|
28
28
|
async deployStack(stack, plan, deployed) {
|
|
29
29
|
const { simAws, accountRegionScope } = this.scope;
|
|
30
|
-
const { transform, caller, resourceOrder, ...options } = cdkOutOptionsFor(stack, plan.stackOptions);
|
|
30
|
+
const { transform, caller, assetsCaller, resourceOrder, ...options } = cdkOutOptionsFor(stack, plan.stackOptions);
|
|
31
31
|
return await simAws
|
|
32
32
|
.accountRegionScope(accountRegionScope.accountId, stack.regionName)
|
|
33
33
|
.cloudFormation()
|
|
@@ -36,6 +36,7 @@ export class SimCfnCdkOutDeployer {
|
|
|
36
36
|
stackName: stack.stackName,
|
|
37
37
|
...options,
|
|
38
38
|
caller: caller ?? plan.caller,
|
|
39
|
+
assetsCaller: assetsCaller ?? plan.assetsCaller,
|
|
39
40
|
resourceOrder: resourceOrder ?? plan.resourceOrder,
|
|
40
41
|
transform: cdkOutBoundTransform(transform, deployed),
|
|
41
42
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SimCdkAssemblyStack } from "../cdk/sim-cdk-assembly-manifest.js";
|
|
2
|
+
import type { SimCfnCdkOutStackOptionsByName } from "./sim-cfn-cdk-out-stack-options.js";
|
|
3
|
+
/**
|
|
4
|
+
* Refuse options keyed against a Stack that is not being deployed.
|
|
5
|
+
*
|
|
6
|
+
* A renamed Stack would otherwise take its bindings, its caller and its
|
|
7
|
+
* transform with it without saying anything, and the deployment that lost them
|
|
8
|
+
* looks like one that never had them.
|
|
9
|
+
*/
|
|
10
|
+
export declare function assertCdkOutOptionsAreDeployed(optionsByName: SimCfnCdkOutStackOptionsByName | undefined, deploying: readonly SimCdkAssemblyStack[]): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refuse options keyed against a Stack that is not being deployed.
|
|
3
|
+
*
|
|
4
|
+
* A renamed Stack would otherwise take its bindings, its caller and its
|
|
5
|
+
* transform with it without saying anything, and the deployment that lost them
|
|
6
|
+
* looks like one that never had them.
|
|
7
|
+
*/
|
|
8
|
+
export function assertCdkOutOptionsAreDeployed(optionsByName, deploying) {
|
|
9
|
+
const names = new Set(deploying.flatMap((stack) => [stack.stackName, stack.artifactId]));
|
|
10
|
+
const unmatched = Object.keys(optionsByName ?? {}).filter((name) => !names.has(name));
|
|
11
|
+
if (unmatched.length > 0) {
|
|
12
|
+
throw new Error(`Options were given for ${unmatched.join(", ")}, which no Stack being deployed is named. The Stacks being deployed are ${deploying.map((stack) => stack.stackName).join(", ")}.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AwsRegionName } from "../../aws/sim-aws-region.js";
|
|
2
2
|
import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
3
3
|
import { type SimCdkAssemblyStack } from "../cdk/sim-cdk-assembly-manifest.js";
|
|
4
|
-
import {
|
|
4
|
+
import type { SimCfnCdkOutStackOptionsByName } from "./sim-cfn-cdk-out-stack-options.js";
|
|
5
5
|
import type { SimCfnResourceOrder } from "../stack/deploy/sim-cfn-resource-order.js";
|
|
6
6
|
export interface SimCloudFormationDeployCdkOutProperties {
|
|
7
7
|
/** The `cdk.out` directory to deploy, holding a `manifest.json`. */
|
|
@@ -23,6 +23,15 @@ export interface SimCloudFormationDeployCdkOutProperties {
|
|
|
23
23
|
* in `stackOptions` overrides for its own Stack.
|
|
24
24
|
*/
|
|
25
25
|
readonly caller?: SimAwsCaller | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* The principal every Stack in the assembly publishes its CDK file assets
|
|
28
|
+
* as, which one named in `stackOptions` overrides for its own Stack.
|
|
29
|
+
*
|
|
30
|
+
* A real `cdk deploy` publishes assets as the file publishing Role and
|
|
31
|
+
* processes each template as the execution Role. Left out, an assembly
|
|
32
|
+
* publishes its assets as `caller`.
|
|
33
|
+
*/
|
|
34
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
26
35
|
/**
|
|
27
36
|
* The order every Stack in the assembly creates Resources with no dependency
|
|
28
37
|
* between them in, which one named in `stackOptions` overrides for its own
|
|
@@ -43,6 +52,7 @@ export interface SimCfnCdkOutPlannedStack extends SimCdkAssemblyStack {
|
|
|
43
52
|
export interface SimCfnCdkOutPlan {
|
|
44
53
|
readonly stacks: readonly SimCfnCdkOutPlannedStack[];
|
|
45
54
|
readonly caller?: SimAwsCaller | undefined;
|
|
55
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
46
56
|
readonly resourceOrder?: SimCfnResourceOrder | undefined;
|
|
47
57
|
readonly stackOptions?: SimCfnCdkOutStackOptionsByName | undefined;
|
|
48
58
|
}
|
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { loadCdkAssemblyStacks, } from "../cdk/sim-cdk-assembly-manifest.js";
|
|
3
3
|
import { orderCdkAssemblyStacks } from "../cdk/sim-cdk-assembly-order.js";
|
|
4
4
|
import { selectCdkAssemblyStacks } from "../cdk/sim-cdk-assembly-selection.js";
|
|
5
|
-
import { assertCdkOutOptionsAreDeployed
|
|
5
|
+
import { assertCdkOutOptionsAreDeployed } from "./sim-cfn-cdk-out-options-deployed.js";
|
|
6
6
|
/**
|
|
7
7
|
* Work out which Stacks to deploy, in what order, and into which region.
|
|
8
8
|
*
|
|
@@ -10,7 +10,7 @@ import { assertCdkOutOptionsAreDeployed, } from "./sim-cfn-cdk-out-stack-options
|
|
|
10
10
|
* an assembly that cannot be deployed says so before any Stack is created.
|
|
11
11
|
*/
|
|
12
12
|
export async function planCdkOutDeployment(properties) {
|
|
13
|
-
const { directoryPath, stackNames, caller, resourceOrder, stackOptions } = cdkOutDeployment(properties.request);
|
|
13
|
+
const { directoryPath, stackNames, caller, assetsCaller, resourceOrder, stackOptions, } = cdkOutDeployment(properties.request);
|
|
14
14
|
const selected = selectCdkAssemblyStacks({
|
|
15
15
|
stacks: await loadCdkAssemblyStacks(directoryPath),
|
|
16
16
|
stackNames,
|
|
@@ -23,6 +23,7 @@ export async function planCdkOutDeployment(properties) {
|
|
|
23
23
|
regionName: stack.regionName ?? properties.defaultRegionName,
|
|
24
24
|
})),
|
|
25
25
|
caller,
|
|
26
|
+
assetsCaller,
|
|
26
27
|
resourceOrder,
|
|
27
28
|
stackOptions,
|
|
28
29
|
};
|
|
@@ -34,6 +34,11 @@ export interface SimCfnCdkOutStackOptions {
|
|
|
34
34
|
* application Stack deployed by another is what this is for.
|
|
35
35
|
*/
|
|
36
36
|
readonly caller?: SimAwsCaller | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* The principal this Stack publishes its CDK file assets as, where the
|
|
39
|
+
* assembly's own assets caller is not the right one for it.
|
|
40
|
+
*/
|
|
41
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
37
42
|
/**
|
|
38
43
|
* The order this Stack creates Resources with no dependency between them in,
|
|
39
44
|
* where the assembly's own order is not the right one for it.
|
|
@@ -53,11 +58,3 @@ export declare function cdkOutOptionsFor(stack: SimCdkAssemblyStack, optionsByNa
|
|
|
53
58
|
* keeps the deployment it was handed while the call goes on deploying.
|
|
54
59
|
*/
|
|
55
60
|
export declare function cdkOutBoundTransform(transform: SimCfnCdkOutTemplateTransform | undefined, deployed: ReadonlyMap<string, SimCfnDeployedStack>): SimCfnTemplateFileTransform | undefined;
|
|
56
|
-
/**
|
|
57
|
-
* Refuse options keyed against a Stack that is not being deployed.
|
|
58
|
-
*
|
|
59
|
-
* A renamed Stack would otherwise take its bindings, its caller and its
|
|
60
|
-
* transform with it without saying anything, and the deployment that lost them
|
|
61
|
-
* looks like one that never had them.
|
|
62
|
-
*/
|
|
63
|
-
export declare function assertCdkOutOptionsAreDeployed(optionsByName: SimCfnCdkOutStackOptionsByName | undefined, deploying: readonly SimCdkAssemblyStack[]): void;
|
|
@@ -17,17 +17,3 @@ export function cdkOutBoundTransform(transform, deployed) {
|
|
|
17
17
|
const deployedSoFar = new Map(deployed);
|
|
18
18
|
return (template) => transform(template, deployedSoFar);
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Refuse options keyed against a Stack that is not being deployed.
|
|
22
|
-
*
|
|
23
|
-
* A renamed Stack would otherwise take its bindings, its caller and its
|
|
24
|
-
* transform with it without saying anything, and the deployment that lost them
|
|
25
|
-
* looks like one that never had them.
|
|
26
|
-
*/
|
|
27
|
-
export function assertCdkOutOptionsAreDeployed(optionsByName, deploying) {
|
|
28
|
-
const names = new Set(deploying.flatMap((stack) => [stack.stackName, stack.artifactId]));
|
|
29
|
-
const unmatched = Object.keys(optionsByName ?? {}).filter((name) => !names.has(name));
|
|
30
|
-
if (unmatched.length > 0) {
|
|
31
|
-
throw new Error(`Options were given for ${unmatched.join(", ")}, which no Stack being deployed is named. The Stacks being deployed are ${deploying.map((stack) => stack.stackName).join(", ")}.`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -24,6 +24,15 @@ export interface SimCloudFormationCreateStackProperties {
|
|
|
24
24
|
* policy denying an Account's root principal then denies.
|
|
25
25
|
*/
|
|
26
26
|
readonly caller?: SimAwsCaller | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The principal the CDK file assets staged beside the template are published
|
|
29
|
+
* as.
|
|
30
|
+
*
|
|
31
|
+
* A real `cdk deploy` publishes them as the file publishing Role and only
|
|
32
|
+
* then processes the template as the execution Role, which is why the two
|
|
33
|
+
* are named apart. Left out, assets are published as `caller`.
|
|
34
|
+
*/
|
|
35
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
27
36
|
/**
|
|
28
37
|
* The order Resources with no dependency between them are created in.
|
|
29
38
|
*
|
|
@@ -59,6 +59,7 @@ export class SimCloudFormationTemplateDeployer {
|
|
|
59
59
|
parameters: properties.parameters,
|
|
60
60
|
bindings: properties.bindings,
|
|
61
61
|
caller: properties.caller,
|
|
62
|
+
assetsCaller: properties.assetsCaller,
|
|
62
63
|
resourceOrder: properties.resourceOrder,
|
|
63
64
|
cdkOutContext: await cdkOutContextForTemplatePath(properties.templatePath),
|
|
64
65
|
});
|
|
@@ -118,6 +119,7 @@ export class SimCloudFormationTemplateDeployer {
|
|
|
118
119
|
cdkOutContext: deployment.cdkOutContext,
|
|
119
120
|
bindings: deployment.bindings,
|
|
120
121
|
caller: deployment.caller,
|
|
122
|
+
assetsCaller: deployment.assetsCaller,
|
|
121
123
|
resourceOrder: deployment.resourceOrder,
|
|
122
124
|
exports: this.exports,
|
|
123
125
|
});
|
|
@@ -20,6 +20,15 @@ export interface SimCloudFormationDeployTemplateFileProperties {
|
|
|
20
20
|
* policy denying an Account's root principal then denies.
|
|
21
21
|
*/
|
|
22
22
|
readonly caller?: SimAwsCaller | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The principal the CDK file assets staged beside the template are published
|
|
25
|
+
* as.
|
|
26
|
+
*
|
|
27
|
+
* A real `cdk deploy` publishes them as the file publishing Role and only
|
|
28
|
+
* then processes the template as the execution Role, which is why the two
|
|
29
|
+
* are named apart. Left out, assets are published as `caller`.
|
|
30
|
+
*/
|
|
31
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
23
32
|
/**
|
|
24
33
|
* The order Resources with no dependency between them are created in.
|
|
25
34
|
*
|
|
@@ -64,6 +73,7 @@ export interface SimCfnLoadedTemplateFile {
|
|
|
64
73
|
readonly parameters?: Record<string, string> | undefined;
|
|
65
74
|
readonly bindings?: readonly SimCfnBinding[] | undefined;
|
|
66
75
|
readonly caller?: SimAwsCaller | undefined;
|
|
76
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
67
77
|
readonly resourceOrder?: SimCfnResourceOrder | undefined;
|
|
68
78
|
readonly cdkOutContext?: SimCdkOutContext | undefined;
|
|
69
79
|
}
|
|
@@ -16,7 +16,7 @@ export class SimCfnTemplateFileLoader {
|
|
|
16
16
|
*/
|
|
17
17
|
async load(properties) {
|
|
18
18
|
const deployment = simCfnTemplateFileDeployment(properties);
|
|
19
|
-
const { templatePath, parameters, bindings, caller, resourceOrder } = deployment;
|
|
19
|
+
const { templatePath, parameters, bindings, caller, assetsCaller, resourceOrder, } = deployment;
|
|
20
20
|
const stackName = deployment.stackName ?? stackNameFromTemplatePath(templatePath);
|
|
21
21
|
// The template is named to a `yulin watch` supervisor, so re-synthing a
|
|
22
22
|
// stack restarts the process that deployed it. Nothing happens outside
|
|
@@ -32,6 +32,7 @@ export class SimCfnTemplateFileLoader {
|
|
|
32
32
|
parameters,
|
|
33
33
|
bindings,
|
|
34
34
|
caller,
|
|
35
|
+
assetsCaller,
|
|
35
36
|
resourceOrder,
|
|
36
37
|
cdkOutContext,
|
|
37
38
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
2
|
+
import type { SimCdkOutContext } from "../cdk/sim-cdk-out-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* What an update can replace on a Stack's deploy context. Anything it leaves
|
|
5
|
+
* out, the Stack goes on using.
|
|
6
|
+
*/
|
|
7
|
+
export interface SimCfnStackUpdateContext {
|
|
8
|
+
readonly cdkOutContext?: SimCdkOutContext | undefined;
|
|
9
|
+
readonly caller?: SimAwsCaller | undefined;
|
|
10
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* What a Stack is deploying from, and who it is deploying as.
|
|
14
|
+
*
|
|
15
|
+
* These three travel together and are the only things an update replaces, so
|
|
16
|
+
* they are held apart from the rest of a Stack's Resource operations. An
|
|
17
|
+
* operation reads them here whenever it runs, rather than closing over the
|
|
18
|
+
* values the deployment started with.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SimCfnStackDeployContext {
|
|
21
|
+
/** The CDK cloud assembly the Stack's template was synthesized into. */
|
|
22
|
+
cdkOutContext: SimCdkOutContext | undefined;
|
|
23
|
+
/** The principal the Stack's Resource work is authorized as. */
|
|
24
|
+
caller: SimAwsCaller | undefined;
|
|
25
|
+
/** The principal the Stack's CDK file assets are published as. */
|
|
26
|
+
assetsCaller: SimAwsCaller | undefined;
|
|
27
|
+
constructor(properties: SimCfnStackUpdateContext);
|
|
28
|
+
/**
|
|
29
|
+
* Take on what an update brings with it, for this and every later operation.
|
|
30
|
+
*
|
|
31
|
+
* A synthesis writes the template and the assets manifest beside it together,
|
|
32
|
+
* so a Stack updated from a re-synthesized template needs the manifest that
|
|
33
|
+
* came with it. Keeping the one the Stack was deployed from would look up the
|
|
34
|
+
* asset a replaced Resource names in a manifest written before it existed.
|
|
35
|
+
*
|
|
36
|
+
* An update naming a caller runs as that one, and the Stack is torn down as
|
|
37
|
+
* it afterwards. An update that names none keeps the deployment's caller, so
|
|
38
|
+
* a Stack updated from a plain template path goes on running as whoever
|
|
39
|
+
* deployed it.
|
|
40
|
+
*/
|
|
41
|
+
useUpdate(properties: SimCfnStackUpdateContext): void;
|
|
42
|
+
/**
|
|
43
|
+
* The principal file assets are published as, which is the deployment's own
|
|
44
|
+
* caller unless the deployment named one for publishing.
|
|
45
|
+
*/
|
|
46
|
+
publishingCaller(): SimAwsCaller | undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a Stack is deploying from, and who it is deploying as.
|
|
3
|
+
*
|
|
4
|
+
* These three travel together and are the only things an update replaces, so
|
|
5
|
+
* they are held apart from the rest of a Stack's Resource operations. An
|
|
6
|
+
* operation reads them here whenever it runs, rather than closing over the
|
|
7
|
+
* values the deployment started with.
|
|
8
|
+
*/
|
|
9
|
+
export class SimCfnStackDeployContext {
|
|
10
|
+
/** The CDK cloud assembly the Stack's template was synthesized into. */
|
|
11
|
+
cdkOutContext;
|
|
12
|
+
/** The principal the Stack's Resource work is authorized as. */
|
|
13
|
+
caller;
|
|
14
|
+
/** The principal the Stack's CDK file assets are published as. */
|
|
15
|
+
assetsCaller;
|
|
16
|
+
constructor(properties) {
|
|
17
|
+
this.cdkOutContext = properties.cdkOutContext;
|
|
18
|
+
this.caller = properties.caller;
|
|
19
|
+
this.assetsCaller = properties.assetsCaller;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Take on what an update brings with it, for this and every later operation.
|
|
23
|
+
*
|
|
24
|
+
* A synthesis writes the template and the assets manifest beside it together,
|
|
25
|
+
* so a Stack updated from a re-synthesized template needs the manifest that
|
|
26
|
+
* came with it. Keeping the one the Stack was deployed from would look up the
|
|
27
|
+
* asset a replaced Resource names in a manifest written before it existed.
|
|
28
|
+
*
|
|
29
|
+
* An update naming a caller runs as that one, and the Stack is torn down as
|
|
30
|
+
* it afterwards. An update that names none keeps the deployment's caller, so
|
|
31
|
+
* a Stack updated from a plain template path goes on running as whoever
|
|
32
|
+
* deployed it.
|
|
33
|
+
*/
|
|
34
|
+
useUpdate(properties) {
|
|
35
|
+
this.cdkOutContext = properties.cdkOutContext ?? this.cdkOutContext;
|
|
36
|
+
this.caller = properties.caller ?? this.caller;
|
|
37
|
+
this.assetsCaller = properties.assetsCaller ?? this.assetsCaller;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The principal file assets are published as, which is the deployment's own
|
|
41
|
+
* caller unless the deployment named one for publishing.
|
|
42
|
+
*/
|
|
43
|
+
publishingCaller() {
|
|
44
|
+
return this.assetsCaller ?? this.caller;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { SimAwsCaller } from "../../aws/caller/sim-aws-caller.js";
|
|
|
4
4
|
import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
|
|
5
5
|
import type { SimCfnBinding } from "../bind/sim-cfn-binding.js";
|
|
6
6
|
import type { SimCdkOutContext } from "../cdk/sim-cdk-out-context.js";
|
|
7
|
+
import { type SimCfnStackUpdateContext } from "./sim-cfn-stack-deploy-context.js";
|
|
7
8
|
import type { SimCfnResource } from "../resource/sim-cfn-resource.js";
|
|
8
9
|
import { SimCfnResourceRetention } from "../resource/delete/sim-cfn-resource-retention.js";
|
|
9
10
|
import type { SimCfnTemplate } from "../template/sim-cfn-template.js";
|
|
@@ -28,6 +29,11 @@ interface SimCfnStackResourceOperationsProperties {
|
|
|
28
29
|
* caller leaves each service to decide the request as the Account root.
|
|
29
30
|
*/
|
|
30
31
|
readonly caller?: SimAwsCaller | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* The principal the Stack's CDK file assets are published as, where that is
|
|
34
|
+
* somebody other than the caller its Resources are created as.
|
|
35
|
+
*/
|
|
36
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
31
37
|
/**
|
|
32
38
|
* The order Resources with no dependency between them are started in.
|
|
33
39
|
*/
|
|
@@ -52,8 +58,7 @@ export declare class SimCfnStackResourceOperations {
|
|
|
52
58
|
private readonly stackName;
|
|
53
59
|
private readonly bindings;
|
|
54
60
|
private readonly resourceOrder;
|
|
55
|
-
private
|
|
56
|
-
private caller;
|
|
61
|
+
private readonly context;
|
|
57
62
|
/**
|
|
58
63
|
* Resources an update kept in simulated AWS.
|
|
59
64
|
*
|
|
@@ -64,23 +69,8 @@ export declare class SimCfnStackResourceOperations {
|
|
|
64
69
|
*/
|
|
65
70
|
private readonly retainedByUpdates;
|
|
66
71
|
constructor(properties: SimCfnStackResourceOperationsProperties);
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
*
|
|
70
|
-
* A synthesis writes the template and the assets manifest beside it together,
|
|
71
|
-
* so a Stack updated from a re-synthesized template needs the manifest that
|
|
72
|
-
* came with it. Keeping the one the Stack was deployed from would look up the
|
|
73
|
-
* asset a replaced Resource names in a manifest written before it existed.
|
|
74
|
-
*
|
|
75
|
-
* An update naming a caller runs as that one, and the Stack is torn down as
|
|
76
|
-
* it afterwards. An update that names none keeps the deployment's caller, so
|
|
77
|
-
* a Stack updated from a plain template path goes on running as whoever
|
|
78
|
-
* deployed it.
|
|
79
|
-
*/
|
|
80
|
-
useUpdate(properties: {
|
|
81
|
-
readonly cdkOutContext?: SimCdkOutContext | undefined;
|
|
82
|
-
readonly caller?: SimAwsCaller | undefined;
|
|
83
|
-
}): void;
|
|
72
|
+
/** Take on what an update brings with it, for every later operation. */
|
|
73
|
+
useUpdate(properties: SimCfnStackUpdateContext): void;
|
|
84
74
|
/**
|
|
85
75
|
* Create every Resource in the given Stack Resource map.
|
|
86
76
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SimCfnStackDeployContext, } from "./sim-cfn-stack-deploy-context.js";
|
|
1
2
|
import { SimCdkAssetsPublisher } from "../cdk/assets/sim-cdk-assets-publisher.js";
|
|
2
3
|
import { SimCfnResourceRetention } from "../resource/delete/sim-cfn-resource-retention.js";
|
|
3
4
|
import { simCfnStackRetainedLogicalIds } from "./teardown/sim-cfn-stack-retained-logical-ids.js";
|
|
@@ -24,8 +25,7 @@ export class SimCfnStackResourceOperations {
|
|
|
24
25
|
stackName;
|
|
25
26
|
bindings;
|
|
26
27
|
resourceOrder;
|
|
27
|
-
|
|
28
|
-
caller;
|
|
28
|
+
context;
|
|
29
29
|
/**
|
|
30
30
|
* Resources an update kept in simulated AWS.
|
|
31
31
|
*
|
|
@@ -36,31 +36,17 @@ export class SimCfnStackResourceOperations {
|
|
|
36
36
|
*/
|
|
37
37
|
retainedByUpdates = [];
|
|
38
38
|
constructor(properties) {
|
|
39
|
-
const { simAws, accountRegionScope, stackName,
|
|
39
|
+
const { simAws, accountRegionScope, stackName, bindings, resourceOrder } = properties;
|
|
40
40
|
this.simAws = simAws;
|
|
41
41
|
this.accountRegionScope = accountRegionScope;
|
|
42
42
|
this.stackName = stackName;
|
|
43
|
-
this.cdkOutContext = cdkOutContext;
|
|
44
43
|
this.bindings = bindings;
|
|
45
|
-
this.caller = caller;
|
|
46
44
|
this.resourceOrder = resourceOrder;
|
|
45
|
+
this.context = new SimCfnStackDeployContext(properties);
|
|
47
46
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Take on what an update brings with it, for this and every later operation.
|
|
50
|
-
*
|
|
51
|
-
* A synthesis writes the template and the assets manifest beside it together,
|
|
52
|
-
* so a Stack updated from a re-synthesized template needs the manifest that
|
|
53
|
-
* came with it. Keeping the one the Stack was deployed from would look up the
|
|
54
|
-
* asset a replaced Resource names in a manifest written before it existed.
|
|
55
|
-
*
|
|
56
|
-
* An update naming a caller runs as that one, and the Stack is torn down as
|
|
57
|
-
* it afterwards. An update that names none keeps the deployment's caller, so
|
|
58
|
-
* a Stack updated from a plain template path goes on running as whoever
|
|
59
|
-
* deployed it.
|
|
60
|
-
*/
|
|
47
|
+
/** Take on what an update brings with it, for every later operation. */
|
|
61
48
|
useUpdate(properties) {
|
|
62
|
-
this.
|
|
63
|
-
this.caller = properties.caller ?? this.caller;
|
|
49
|
+
this.context.useUpdate(properties);
|
|
64
50
|
}
|
|
65
51
|
/**
|
|
66
52
|
* Create every Resource in the given Stack Resource map.
|
|
@@ -120,7 +106,7 @@ export class SimCfnStackResourceOperations {
|
|
|
120
106
|
simAws: this.simAws,
|
|
121
107
|
currentResources,
|
|
122
108
|
updatedResources,
|
|
123
|
-
caller: this.caller,
|
|
109
|
+
caller: this.context.caller,
|
|
124
110
|
});
|
|
125
111
|
}));
|
|
126
112
|
}
|
|
@@ -173,8 +159,8 @@ export class SimCfnStackResourceOperations {
|
|
|
173
159
|
simAws: this.simAws,
|
|
174
160
|
accountRegionScope: this.accountRegionScope,
|
|
175
161
|
stackName: this.stackName,
|
|
176
|
-
cdkOutContext: this.cdkOutContext,
|
|
177
|
-
|
|
162
|
+
cdkOutContext: this.context.cdkOutContext,
|
|
163
|
+
assetsCaller: this.context.publishingCaller(),
|
|
178
164
|
}).publish();
|
|
179
165
|
}
|
|
180
166
|
creator(resources) {
|
|
@@ -182,9 +168,9 @@ export class SimCfnStackResourceOperations {
|
|
|
182
168
|
simAws: this.simAws,
|
|
183
169
|
resources,
|
|
184
170
|
stackName: this.stackName,
|
|
185
|
-
cdkOutContext: this.cdkOutContext,
|
|
171
|
+
cdkOutContext: this.context.cdkOutContext,
|
|
186
172
|
bindings: this.bindings,
|
|
187
|
-
caller: this.caller,
|
|
173
|
+
caller: this.context.caller,
|
|
188
174
|
resourceOrder: this.resourceOrder,
|
|
189
175
|
});
|
|
190
176
|
}
|
|
@@ -193,7 +179,7 @@ export class SimCfnStackResourceOperations {
|
|
|
193
179
|
simAws: this.simAws,
|
|
194
180
|
resources,
|
|
195
181
|
stackName: this.stackName,
|
|
196
|
-
caller: this.caller,
|
|
182
|
+
caller: this.context.caller,
|
|
197
183
|
retention,
|
|
198
184
|
});
|
|
199
185
|
}
|
|
@@ -38,7 +38,7 @@ export class SimCfnStack {
|
|
|
38
38
|
stackOutputs;
|
|
39
39
|
cfnTemplate;
|
|
40
40
|
constructor(properties) {
|
|
41
|
-
const { simAws, accountRegionScope, background, stackName, stackId, template, cdkOutContext, bindings, caller, resourceOrder, exports, } = properties;
|
|
41
|
+
const { simAws, accountRegionScope, background, stackName, stackId, template, cdkOutContext, bindings, caller, assetsCaller, resourceOrder, exports, } = properties;
|
|
42
42
|
this.background = background;
|
|
43
43
|
this.stackName = stackName;
|
|
44
44
|
this.stackId = stackId;
|
|
@@ -61,6 +61,7 @@ export class SimCfnStack {
|
|
|
61
61
|
cdkOutContext,
|
|
62
62
|
bindings,
|
|
63
63
|
caller,
|
|
64
|
+
assetsCaller,
|
|
64
65
|
resourceOrder,
|
|
65
66
|
});
|
|
66
67
|
this.lifecycle = new SimCfnStackDeploymentLifecycle({
|
|
@@ -24,6 +24,11 @@ export interface SimCfnStackUpdateProperties {
|
|
|
24
24
|
* The Stack goes on using it, as it does the cloud assembly.
|
|
25
25
|
*/
|
|
26
26
|
readonly caller?: SimAwsCaller | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The principal to publish the re-synthesized file assets as, for an update
|
|
29
|
+
* that names one. The Stack goes on using it too.
|
|
30
|
+
*/
|
|
31
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
27
32
|
}
|
|
28
33
|
export interface SimCloudFormationStackProperties {
|
|
29
34
|
readonly simAws: SimAws;
|
|
@@ -44,6 +49,15 @@ export interface SimCloudFormationStackProperties {
|
|
|
44
49
|
* simulation.
|
|
45
50
|
*/
|
|
46
51
|
readonly caller?: SimAwsCaller | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* The principal the CDK file assets staged beside the template are published
|
|
54
|
+
* as.
|
|
55
|
+
*
|
|
56
|
+
* A real `cdk deploy` publishes them as the file publishing Role and only
|
|
57
|
+
* then processes the template as the execution Role, which is why the two
|
|
58
|
+
* are named apart. Left out, assets are published as `caller`.
|
|
59
|
+
*/
|
|
60
|
+
readonly assetsCaller?: SimAwsCaller | undefined;
|
|
47
61
|
/**
|
|
48
62
|
* The order this Stack starts Resources with no dependency between them in.
|
|
49
63
|
* The template's own order unless the deployment asked for another one.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { BackgroundScheduler } from "../../../util/background/background.js";
|
|
2
|
+
import type { SimAwsAccountRegionScope } from "../../aws/sim-aws-account-region-scope.js";
|
|
3
|
+
import { SimS3Bucket, type SimS3BucketName } from "./sim-s3-bucket.js";
|
|
4
|
+
import type { SimS3GlobalRegistry } from "../sim-s3-global-registry.js";
|
|
5
|
+
interface SimS3BucketMakerProperties {
|
|
6
|
+
readonly accountRegionScope: SimAwsAccountRegionScope;
|
|
7
|
+
readonly buckets: Map<SimS3BucketName, SimS3Bucket>;
|
|
8
|
+
readonly s3GlobalRegistry: SimS3GlobalRegistry;
|
|
9
|
+
readonly background: BackgroundScheduler;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Puts a Bucket into a simulated S3 scope, once something has decided it may
|
|
13
|
+
* be there.
|
|
14
|
+
*
|
|
15
|
+
* `CreateBucketCommand` decides that by authorizing the caller. A Bucket real
|
|
16
|
+
* AWS provisions outside the deployment being simulated, such as the CDK
|
|
17
|
+
* bootstrap staging Bucket, has no caller to authorize and comes through
|
|
18
|
+
* `SimS3.makeSimBucket` instead. Both arrive at the same Bucket registered in
|
|
19
|
+
* the same two places, because the name check and the registration are here
|
|
20
|
+
* rather than in the command handler.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SimS3BucketMaker {
|
|
23
|
+
private readonly properties;
|
|
24
|
+
constructor(properties: SimS3BucketMakerProperties);
|
|
25
|
+
/**
|
|
26
|
+
* Make a Bucket of the given name, reporting a name this scope cannot take
|
|
27
|
+
* the way `CreateBucketCommand` reports it.
|
|
28
|
+
*/
|
|
29
|
+
make(bucketName: string): SimS3Bucket;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SimS3BucketNameAvailability } from "./name-availability/sim-s3-bucket-name-availability.js";
|
|
2
|
+
import { validateS3BucketName } from "./validate/validate-s3-bucket-name.js";
|
|
3
|
+
import { SimS3Bucket } from "./sim-s3-bucket.js";
|
|
4
|
+
/**
|
|
5
|
+
* Puts a Bucket into a simulated S3 scope, once something has decided it may
|
|
6
|
+
* be there.
|
|
7
|
+
*
|
|
8
|
+
* `CreateBucketCommand` decides that by authorizing the caller. A Bucket real
|
|
9
|
+
* AWS provisions outside the deployment being simulated, such as the CDK
|
|
10
|
+
* bootstrap staging Bucket, has no caller to authorize and comes through
|
|
11
|
+
* `SimS3.makeSimBucket` instead. Both arrive at the same Bucket registered in
|
|
12
|
+
* the same two places, because the name check and the registration are here
|
|
13
|
+
* rather than in the command handler.
|
|
14
|
+
*/
|
|
15
|
+
export class SimS3BucketMaker {
|
|
16
|
+
properties;
|
|
17
|
+
constructor(properties) {
|
|
18
|
+
this.properties = properties;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Make a Bucket of the given name, reporting a name this scope cannot take
|
|
22
|
+
* the way `CreateBucketCommand` reports it.
|
|
23
|
+
*/
|
|
24
|
+
make(bucketName) {
|
|
25
|
+
const { accountRegionScope, buckets, s3GlobalRegistry, background } = this.properties;
|
|
26
|
+
validateS3BucketName(bucketName);
|
|
27
|
+
new SimS3BucketNameAvailability({
|
|
28
|
+
accountRegionScope,
|
|
29
|
+
buckets,
|
|
30
|
+
s3GlobalRegistry,
|
|
31
|
+
}).ensureCanCreateBucketNamed(bucketName);
|
|
32
|
+
const bucket = new SimS3Bucket({
|
|
33
|
+
bucketName,
|
|
34
|
+
accountRegionScope,
|
|
35
|
+
clock: background,
|
|
36
|
+
});
|
|
37
|
+
buckets.set(bucketName, bucket);
|
|
38
|
+
s3GlobalRegistry.registerBucket(bucketName, accountRegionScope);
|
|
39
|
+
return bucket;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandHandler } from "../../../../command/command-handler.js";
|
|
2
2
|
import type { SimCreateBucketCommand, SimCreateBucketCommandOutput } from "./create-bucket.command.js";
|
|
3
|
-
import { SimS3Bucket } from "../../bucket/sim-s3-bucket.js";
|
|
3
|
+
import type { SimS3Bucket, SimS3BucketName } from "../../bucket/sim-s3-bucket.js";
|
|
4
4
|
import type { SimS3GlobalRegistry } from "../../sim-s3-global-registry.js";
|
|
5
5
|
import type { SimAwsAccountRegionScope } from "../../../aws/sim-aws-account-region-scope.js";
|
|
6
6
|
import { type BackgroundScheduler } from "../../../../util/background/background.js";
|
|
@@ -8,7 +8,7 @@ import { type SimIamInterServiceAuthZ } from "../../../iam/authorize/sim-iam-int
|
|
|
8
8
|
import type { SimS3RequestOptions } from "../sim-s3-request-options.js";
|
|
9
9
|
interface CreateBucketCommandHandlerProperties {
|
|
10
10
|
readonly accountRegionScope: SimAwsAccountRegionScope;
|
|
11
|
-
readonly buckets: Map<
|
|
11
|
+
readonly buckets: Map<SimS3BucketName, SimS3Bucket>;
|
|
12
12
|
readonly s3GlobalRegistry: SimS3GlobalRegistry;
|
|
13
13
|
readonly iam?: SimIamInterServiceAuthZ;
|
|
14
14
|
readonly background?: BackgroundScheduler;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { SimS3Bucket } from "../../bucket/sim-s3-bucket.js";
|
|
2
1
|
import { assertDefined } from "../../../../util/type-guard/defined.js";
|
|
3
2
|
import { BackgroundTasks, } from "../../../../util/background/background.js";
|
|
4
|
-
import {
|
|
3
|
+
import { SimS3BucketMaker } from "../../bucket/sim-s3-bucket-maker.js";
|
|
5
4
|
import { validateS3BucketName } from "../../bucket/validate/validate-s3-bucket-name.js";
|
|
6
5
|
import { SimIamAllowAllAuth, } from "../../../iam/authorize/sim-iam-inter-service-auth-z.js";
|
|
7
6
|
import { SimIamAccessDenied } from "../../../iam/error/sim-iam.error.js";
|
|
@@ -49,19 +48,12 @@ export class CreateBucketCommandHandler {
|
|
|
49
48
|
resource,
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
|
-
|
|
51
|
+
new SimS3BucketMaker({
|
|
53
52
|
accountRegionScope: this.accountRegionScope,
|
|
54
53
|
buckets: this.buckets,
|
|
55
54
|
s3GlobalRegistry: this.s3GlobalRegistry,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const bucket = new SimS3Bucket({
|
|
59
|
-
bucketName,
|
|
60
|
-
accountRegionScope: this.accountRegionScope,
|
|
61
|
-
clock: this.background,
|
|
62
|
-
});
|
|
63
|
-
this.buckets.set(bucketName, bucket);
|
|
64
|
-
this.s3GlobalRegistry.registerBucket(bucketName, this.accountRegionScope);
|
|
55
|
+
background: this.background,
|
|
56
|
+
}).make(bucketName);
|
|
65
57
|
return {
|
|
66
58
|
BucketArn: resource,
|
|
67
59
|
Location: `/${bucketName}`,
|
|
@@ -63,6 +63,12 @@ export declare class SimS3Commands {
|
|
|
63
63
|
readonly objectTagging: SimS3ObjectTaggingCommands;
|
|
64
64
|
readonly multipartUploads: SimS3MultipartCommands;
|
|
65
65
|
readonly objectNotifier: SimS3ObjectNotifier;
|
|
66
|
+
/**
|
|
67
|
+
* The scheduler and clock every command area here shares, which a
|
|
68
|
+
* simulator-only control on the service facade needs to hand a Bucket it
|
|
69
|
+
* makes outside the commands.
|
|
70
|
+
*/
|
|
71
|
+
readonly background: BackgroundScheduler;
|
|
66
72
|
constructor(properties: SimS3CommandsProperties);
|
|
67
73
|
}
|
|
68
74
|
export {};
|
|
@@ -35,8 +35,15 @@ export class SimS3Commands {
|
|
|
35
35
|
objectTagging;
|
|
36
36
|
multipartUploads;
|
|
37
37
|
objectNotifier;
|
|
38
|
+
/**
|
|
39
|
+
* The scheduler and clock every command area here shares, which a
|
|
40
|
+
* simulator-only control on the service facade needs to hand a Bucket it
|
|
41
|
+
* makes outside the commands.
|
|
42
|
+
*/
|
|
43
|
+
background;
|
|
38
44
|
constructor(properties) {
|
|
39
45
|
const { background = new BackgroundTasks(), notificationDestinations = new SimS3NoNotificationDestinations(), } = properties;
|
|
46
|
+
this.background = background;
|
|
40
47
|
const iam = simIamInRegion(properties.iam, properties.accountRegionScope.regionName);
|
|
41
48
|
this.objectNotifier = new SimS3ObjectNotifier({
|
|
42
49
|
destinations: notificationDestinations,
|
|
@@ -18,9 +18,25 @@ import type { SimS3MountFilesystemOptions } from "./mount/sim-s3-mount.type.js";
|
|
|
18
18
|
*/
|
|
19
19
|
export declare class SimS3 extends SimS3Operations {
|
|
20
20
|
private readonly bucketAccess;
|
|
21
|
+
private readonly bucketMaker;
|
|
21
22
|
private readonly cfnFactory;
|
|
22
23
|
private readonly sdkRouter;
|
|
23
24
|
constructor(properties?: SimS3Properties);
|
|
25
|
+
/**
|
|
26
|
+
* Make a Bucket in this scope without a `CreateBucketCommand`, and so
|
|
27
|
+
* without a principal to authorize.
|
|
28
|
+
*
|
|
29
|
+
* This is for a Bucket real AWS has provisioned before the code under test
|
|
30
|
+
* runs, which nothing in the simulation is deploying. The CDK bootstrap
|
|
31
|
+
* staging Bucket is the one the simulator makes for itself: `cdk deploy`
|
|
32
|
+
* publishes assets into a Bucket the bootstrap stack created, and a
|
|
33
|
+
* deployment that had to create it would be charged permissions no real
|
|
34
|
+
* deployment needs.
|
|
35
|
+
*
|
|
36
|
+
* A name this scope cannot take is reported the way `CreateBucketCommand`
|
|
37
|
+
* reports it.
|
|
38
|
+
*/
|
|
39
|
+
makeSimBucket(bucketName: SimS3BucketName | string): SimS3Bucket;
|
|
24
40
|
/**
|
|
25
41
|
* Change how many keys one page of an Object listing holds, which real S3
|
|
26
42
|
* fixes at a thousand.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SimS3GlobalRegistry } from "./sim-s3-global-registry.js";
|
|
2
2
|
import { SimS3BucketAccess } from "./bucket/sim-s3-bucket-access.js";
|
|
3
|
+
import { SimS3BucketMaker } from "./bucket/sim-s3-bucket-maker.js";
|
|
3
4
|
import { SimS3CloudFormationResourceFactory } from "./cfn/sim-cfn-s3-resource-factory.js";
|
|
4
5
|
import { simAwsAccountRegionScopeFactory } from "../aws/sim-aws-account-region-scope.factory.js";
|
|
5
6
|
import { SimS3Commands } from "./sim-s3-commands.js";
|
|
@@ -16,6 +17,7 @@ import { SimS3SdkCommandRouter } from "./sdk/sim-s3-sdk-command-router.js";
|
|
|
16
17
|
*/
|
|
17
18
|
export class SimS3 extends SimS3Operations {
|
|
18
19
|
bucketAccess;
|
|
20
|
+
bucketMaker;
|
|
19
21
|
cfnFactory = new SimS3CloudFormationResourceFactory(this);
|
|
20
22
|
sdkRouter = new SimS3SdkCommandRouter(this);
|
|
21
23
|
constructor(properties = {}) {
|
|
@@ -32,6 +34,29 @@ export class SimS3 extends SimS3Operations {
|
|
|
32
34
|
accountRegionScope,
|
|
33
35
|
s3GlobalRegistry,
|
|
34
36
|
});
|
|
37
|
+
this.bucketMaker = new SimS3BucketMaker({
|
|
38
|
+
accountRegionScope,
|
|
39
|
+
buckets,
|
|
40
|
+
s3GlobalRegistry,
|
|
41
|
+
background: this.commands.background,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Make a Bucket in this scope without a `CreateBucketCommand`, and so
|
|
46
|
+
* without a principal to authorize.
|
|
47
|
+
*
|
|
48
|
+
* This is for a Bucket real AWS has provisioned before the code under test
|
|
49
|
+
* runs, which nothing in the simulation is deploying. The CDK bootstrap
|
|
50
|
+
* staging Bucket is the one the simulator makes for itself: `cdk deploy`
|
|
51
|
+
* publishes assets into a Bucket the bootstrap stack created, and a
|
|
52
|
+
* deployment that had to create it would be charged permissions no real
|
|
53
|
+
* deployment needs.
|
|
54
|
+
*
|
|
55
|
+
* A name this scope cannot take is reported the way `CreateBucketCommand`
|
|
56
|
+
* reports it.
|
|
57
|
+
*/
|
|
58
|
+
makeSimBucket(bucketName) {
|
|
59
|
+
return this.bucketMaker.make(bucketName);
|
|
35
60
|
}
|
|
36
61
|
/**
|
|
37
62
|
* Change how many keys one page of an Object listing holds, which real S3
|
|
@@ -2115,8 +2115,62 @@ const stacks = await simAws.cloudFormation().deployCdkOut({
|
|
|
2115
2115
|
console.log(stacks.get("PipelineStack")?.stackName);
|
|
2116
2116
|
```
|
|
2117
2117
|
|
|
2118
|
-
|
|
2119
|
-
|
|
2118
|
+
### The principal a CDK asset is published as
|
|
2119
|
+
|
|
2120
|
+
A real `cdk deploy` runs in two phases under two Roles. `cdk-assets` publishes every staged file
|
|
2121
|
+
asset to the bootstrap staging bucket as the file publishing Role, and CloudFormation then processes
|
|
2122
|
+
the template as the execution Role. `assetsCaller` names the first of those, beside the `caller`
|
|
2123
|
+
naming the second.
|
|
2124
|
+
|
|
2125
|
+
```typescript sim-cloudformation-assets-caller
|
|
2126
|
+
/**
|
|
2127
|
+
* Publishing a Stack's CDK file assets as the file publishing Role.
|
|
2128
|
+
*/
|
|
2129
|
+
|
|
2130
|
+
import { SimAws } from "@kensio/yulin";
|
|
2131
|
+
|
|
2132
|
+
const simAws = new SimAws({
|
|
2133
|
+
defaultAccountId: "123456789012",
|
|
2134
|
+
defaultRegionName: "eu-west-2",
|
|
2135
|
+
});
|
|
2136
|
+
|
|
2137
|
+
const publisher = await simAws.iam().makeDeployRole({
|
|
2138
|
+
roleName: "cdk-file-publishing",
|
|
2139
|
+
policyDocument: {
|
|
2140
|
+
Version: "2012-10-17",
|
|
2141
|
+
Statement: {
|
|
2142
|
+
Effect: "Allow",
|
|
2143
|
+
Action: ["s3:GetObject*", "s3:GetBucket*", "s3:List*", "s3:PutObject"],
|
|
2144
|
+
Resource: "arn:aws:s3:::cdk-hnb659fds-assets-*",
|
|
2145
|
+
},
|
|
2146
|
+
},
|
|
2147
|
+
});
|
|
2148
|
+
|
|
2149
|
+
const executor = await simAws.iam().makeDeployRole({
|
|
2150
|
+
roleName: "cdk-exec",
|
|
2151
|
+
policyDocument: {
|
|
2152
|
+
Version: "2012-10-17",
|
|
2153
|
+
Statement: { Effect: "Allow", Action: "s3:*", Resource: "*" },
|
|
2154
|
+
},
|
|
2155
|
+
});
|
|
2156
|
+
|
|
2157
|
+
const stacks = await simAws.cloudFormation().deployCdkOut({
|
|
2158
|
+
directoryPath: "cdk.out",
|
|
2159
|
+
caller: executor,
|
|
2160
|
+
assetsCaller: publisher,
|
|
2161
|
+
});
|
|
2162
|
+
|
|
2163
|
+
console.log(stacks.size);
|
|
2164
|
+
```
|
|
2165
|
+
|
|
2166
|
+
`deployTemplate(...)` and `deployTemplateFile(...)` take the same option, and a Stack in an assembly
|
|
2167
|
+
names its own in `stackOptions`. A deployment that names no `assetsCaller` publishes its assets as
|
|
2168
|
+
`caller`, the way every deployment did before the two could be told apart.
|
|
2169
|
+
|
|
2170
|
+
The CDK bootstrap stack provisions the staging bucket, long before either Role runs. Yulin stands in
|
|
2171
|
+
for that and makes the bucket outside IAM when the first asset is published into it. So a Role
|
|
2172
|
+
holding only what a scoped execution policy grants on `cdk-hnb659fds-assets-*` deploys a cloud
|
|
2173
|
+
assembly with file assets, with no `s3:CreateBucket` or `s3:PutObject` added to it.
|
|
2120
2174
|
|
|
2121
2175
|
## Editing a synthesized template before deploying it
|
|
2122
2176
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kensio/yulin",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.5",
|
|
4
4
|
"description": "AWS system behaviour simulation for isolated unit testing",
|
|
5
5
|
"repository": "https://github.com/KensioSoftware/yulin",
|
|
6
6
|
"homepage": "https://yulinsim.dev/",
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
"eslint-plugin-jsdoc": "^63.3.2",
|
|
294
294
|
"eslint-plugin-no-secrets": "^2.3.3",
|
|
295
295
|
"eslint-plugin-security": "^4.0.1",
|
|
296
|
-
"eslint-plugin-unicorn": "^
|
|
296
|
+
"eslint-plugin-unicorn": "^73.0.0",
|
|
297
297
|
"execa": "^10.0.0",
|
|
298
298
|
"fta-cli": "^3.0.0",
|
|
299
299
|
"hyparquet": "^1.29.2",
|