@kensio/yulin 1.21.26 → 1.21.28
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/config/eslint/cffjs2.eslint.config.js +4 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-list-type.d.ts +7 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-list-type.js +9 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-values.d.ts +10 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameter-values.js +20 -0
- package/dist/service/cloudformation/parameters/sim-cfn-parameters.type.d.ts +7 -5
- package/dist/service/cloudformation/parameters/store/sim-cfn-parameter-store-value-type.js +2 -1
- package/dist/service/cloudformation/template/node/fn/join/sim-cfn-fn-join.d.ts +19 -14
- package/dist/service/cloudformation/template/node/fn/join/sim-cfn-fn-join.js +47 -28
- package/dist/service/cloudformation/template/parse/fn/join/sim-cfn-fn-join-parser.d.ts +7 -4
- package/dist/service/cloudformation/template/parse/fn/join/sim-cfn-fn-join-parser.js +11 -7
- package/dist/service/eventbridge/bus/sim-event-bus-name.d.ts +4 -0
- package/dist/service/eventbridge/bus/sim-event-bus-name.js +17 -12
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-creator.js +8 -1
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.d.ts +5 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.js +14 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-creator.js +2 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-target-delivery.d.ts +15 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-target-delivery.js +53 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-targets.d.ts +4 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-targets.js +7 -3
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.d.ts +5 -0
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.js +7 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-create-event-bus.d.ts +7 -1
- package/dist/service/eventbridge/command/bus/sim-event-bridge-create-event-bus.js +7 -1
- package/dist/service/eventbridge/command/bus/sim-event-bridge-partner-bus.d.ts +24 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-partner-bus.js +44 -0
- package/dist/service/eventbridge/command/bus/sim-event-bridge-unsimulated-bus-input.js +0 -5
- package/dist/service/eventbridge/command/put-events/sim-event-bridge-authorized-entries.js +8 -0
- package/dist/service/eventbridge/command/sim-event-bridge-command.types.d.ts +1 -0
- package/dist/service/eventbridge/command/sim-event-bridge-commands.d.ts +6 -0
- package/dist/service/eventbridge/command/sim-event-bridge-commands.js +19 -1
- package/dist/service/eventbridge/command/source/sim-event-bridge-describe-event-source.d.ts +35 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-describe-event-source.js +46 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-put-partner-events.d.ts +41 -0
- package/dist/service/eventbridge/command/source/sim-event-bridge-put-partner-events.js +82 -0
- package/dist/service/eventbridge/command/source/source.command.d.ts +59 -0
- package/dist/service/eventbridge/command/source/source.command.js +1 -0
- package/dist/service/eventbridge/command/target/sim-event-bridge-target-commands.js +2 -0
- package/dist/service/eventbridge/command/target/sim-event-bridge-unsimulated-target-input.js +2 -12
- package/dist/service/eventbridge/command/target/target.command.d.ts +8 -5
- package/dist/service/eventbridge/delivery/sim-aws-event-bridge-delivery-targets.d.ts +6 -1
- package/dist/service/eventbridge/delivery/sim-aws-event-bridge-delivery-targets.js +16 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-attributes.d.ts +9 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-attributes.js +47 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-queue.d.ts +24 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-dead-letter-queue.js +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-attempt.d.ts +41 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-attempt.js +97 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-queue.js +7 -37
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-retries.test-support.d.ts +25 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery-retries.test-support.js +60 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-delivery.d.ts +22 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-failing-targets.test-support.d.ts +23 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-failing-targets.test-support.js +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-no-delivery-targets.d.ts +5 -1
- package/dist/service/eventbridge/delivery/sim-event-bridge-no-delivery-targets.js +9 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-queue-message.d.ts +28 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-queue-message.js +45 -0
- package/dist/service/eventbridge/delivery/sim-event-bridge-target-delivery.d.ts +4 -1
- package/dist/service/eventbridge/delivery/sim-event-bridge-target-delivery.js +19 -14
- package/dist/service/eventbridge/index.d.ts +2 -0
- package/dist/service/eventbridge/index.js +2 -0
- package/dist/service/eventbridge/routing/sim-event-bridge-router.js +1 -0
- package/dist/service/eventbridge/sdk/sim-event-bridge-sdk-command-router.js +4 -0
- package/dist/service/eventbridge/sim-event-bridge-inspection.d.ts +10 -0
- package/dist/service/eventbridge/sim-event-bridge-inspection.js +9 -0
- package/dist/service/eventbridge/sim-event-bridge-partners.d.ts +38 -0
- package/dist/service/eventbridge/sim-event-bridge-partners.js +43 -0
- package/dist/service/eventbridge/sim-event-bridge.d.ts +12 -12
- package/dist/service/eventbridge/sim-event-bridge.js +14 -11
- package/dist/service/eventbridge/source/sim-partner-event-source-name.d.ts +28 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-name.js +62 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-store.d.ts +18 -0
- package/dist/service/eventbridge/source/sim-partner-event-source-store.js +29 -0
- package/dist/service/eventbridge/source/sim-partner-event-source.d.ts +46 -0
- package/dist/service/eventbridge/source/sim-partner-event-source.js +43 -0
- package/dist/service/eventbridge/target/sim-event-target-dead-letter-config.d.ts +28 -0
- package/dist/service/eventbridge/target/sim-event-target-dead-letter-config.js +42 -0
- package/dist/service/eventbridge/target/sim-event-target-retry-policy.d.ts +28 -0
- package/dist/service/eventbridge/target/sim-event-target-retry-policy.js +53 -0
- package/dist/service/eventbridge/target/sim-event-target.d.ts +17 -0
- package/dist/service/eventbridge/target/sim-event-target.js +19 -0
- package/docs/serve/README.md +1 -1
- package/docs/services/cloudformation/README.md +28 -5
- package/docs/services/dynamodb/README.md +2 -2
- package/docs/services/eventbridge/README.md +223 -6
- package/docs/services/s3/README.md +1 -1
- package/docs/services/sqs/README.md +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A target's `RetryPolicy`, as a request or a template carries it.
|
|
3
|
+
*/
|
|
4
|
+
export interface SimEventTargetRetryPolicyInput {
|
|
5
|
+
readonly MaximumEventAgeInSeconds?: number | undefined;
|
|
6
|
+
readonly MaximumRetryAttempts?: number | undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The retry limits one target declares, and the values they come to.
|
|
10
|
+
*
|
|
11
|
+
* A limit the policy leaves out takes EventBridge's own default, which is 185
|
|
12
|
+
* retries over at most 24 hours.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SimEventTargetRetryPolicy {
|
|
15
|
+
readonly declared: SimEventTargetRetryPolicyInput;
|
|
16
|
+
readonly maximumEventAgeInSeconds: number;
|
|
17
|
+
readonly maximumRetryAttempts: number;
|
|
18
|
+
private constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Read the retry policy a target may leave out.
|
|
21
|
+
*/
|
|
22
|
+
static optional(policy: SimEventTargetRetryPolicyInput | undefined): SimEventTargetRetryPolicy | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Read a retry policy, refusing values outside EventBridge's ranges.
|
|
25
|
+
*/
|
|
26
|
+
static of(policy: SimEventTargetRetryPolicyInput): SimEventTargetRetryPolicy;
|
|
27
|
+
private static requireWholeNumber;
|
|
28
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SimEventBridgeValidationException } from "../error/sim-event-bridge.error.js";
|
|
2
|
+
/**
|
|
3
|
+
* The longest EventBridge keeps retrying an event, and the most retries it
|
|
4
|
+
* makes, when a target's retry policy leaves either out.
|
|
5
|
+
*/
|
|
6
|
+
const defaultMaximumEventAgeInSeconds = 86_400;
|
|
7
|
+
const defaultMaximumRetryAttempts = 185;
|
|
8
|
+
const minimumEventAgeInSeconds = 60;
|
|
9
|
+
/**
|
|
10
|
+
* The retry limits one target declares, and the values they come to.
|
|
11
|
+
*
|
|
12
|
+
* A limit the policy leaves out takes EventBridge's own default, which is 185
|
|
13
|
+
* retries over at most 24 hours.
|
|
14
|
+
*/
|
|
15
|
+
export class SimEventTargetRetryPolicy {
|
|
16
|
+
declared;
|
|
17
|
+
maximumEventAgeInSeconds;
|
|
18
|
+
maximumRetryAttempts;
|
|
19
|
+
constructor(policy) {
|
|
20
|
+
this.declared = { ...policy };
|
|
21
|
+
this.maximumEventAgeInSeconds =
|
|
22
|
+
policy.MaximumEventAgeInSeconds ?? defaultMaximumEventAgeInSeconds;
|
|
23
|
+
this.maximumRetryAttempts =
|
|
24
|
+
policy.MaximumRetryAttempts ?? defaultMaximumRetryAttempts;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read the retry policy a target may leave out.
|
|
28
|
+
*/
|
|
29
|
+
static optional(policy) {
|
|
30
|
+
if (policy === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return this.of(policy);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read a retry policy, refusing values outside EventBridge's ranges.
|
|
37
|
+
*/
|
|
38
|
+
static of(policy) {
|
|
39
|
+
this.requireWholeNumber("MaximumEventAgeInSeconds", policy.MaximumEventAgeInSeconds, minimumEventAgeInSeconds, defaultMaximumEventAgeInSeconds);
|
|
40
|
+
this.requireWholeNumber("MaximumRetryAttempts", policy.MaximumRetryAttempts, 0, defaultMaximumRetryAttempts);
|
|
41
|
+
return new this(policy);
|
|
42
|
+
}
|
|
43
|
+
static requireWholeNumber(name, value, minimum, maximum) {
|
|
44
|
+
if (value === undefined) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
|
|
48
|
+
throw new SimEventBridgeValidationException(`Invalid parameter: Target RetryPolicy ${name} Reason: it is a whole ` +
|
|
49
|
+
`number between ${String(minimum)} and ${String(maximum)}, and ` +
|
|
50
|
+
`${String(value)} is not.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { SimEventTargetArn } from "./sim-event-target-arn.js";
|
|
2
|
+
import { SimEventTargetDeadLetterConfig, type SimEventTargetDeadLetterConfigInput } from "./sim-event-target-dead-letter-config.js";
|
|
3
|
+
import { SimEventTargetRetryPolicy, type SimEventTargetRetryPolicyInput } from "./sim-event-target-retry-policy.js";
|
|
2
4
|
import { SimEventTargetEcs, type SimEventTargetTaskProperties } from "./sim-event-target-ecs.js";
|
|
3
5
|
/**
|
|
4
6
|
* One place a rule sends the events it matches.
|
|
@@ -29,6 +31,19 @@ export declare class SimEventTarget {
|
|
|
29
31
|
* is what the task overrides instead.
|
|
30
32
|
*/
|
|
31
33
|
readonly ecs: SimEventTargetEcs | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* How long and how often a failed delivery is retried, where the target
|
|
36
|
+
* says.
|
|
37
|
+
*
|
|
38
|
+
* A target without one is delivered once. Real EventBridge retries such a
|
|
39
|
+
* target for up to 24 hours by default, and that divergence is documented.
|
|
40
|
+
*/
|
|
41
|
+
readonly retryPolicy: SimEventTargetRetryPolicy | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* The queue an event goes to once delivery is given up, where the target
|
|
44
|
+
* names one.
|
|
45
|
+
*/
|
|
46
|
+
readonly deadLetterConfig: SimEventTargetDeadLetterConfig | undefined;
|
|
32
47
|
private constructor();
|
|
33
48
|
/**
|
|
34
49
|
* Read a target from request input.
|
|
@@ -36,6 +51,8 @@ export declare class SimEventTarget {
|
|
|
36
51
|
static of(properties: SimEventTargetTaskProperties & {
|
|
37
52
|
readonly Id?: string | undefined;
|
|
38
53
|
readonly Arn?: string | undefined;
|
|
54
|
+
readonly RetryPolicy?: SimEventTargetRetryPolicyInput | undefined;
|
|
55
|
+
readonly DeadLetterConfig?: SimEventTargetDeadLetterConfigInput | undefined;
|
|
39
56
|
}): SimEventTarget;
|
|
40
57
|
/**
|
|
41
58
|
* Read a target's fixed input, which has to be JSON.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { SimEventBridgeValidationException } from "../error/sim-event-bridge.error.js";
|
|
2
2
|
import { SimEventTargetArn } from "./sim-event-target-arn.js";
|
|
3
|
+
import { SimEventTargetDeadLetterConfig, } from "./sim-event-target-dead-letter-config.js";
|
|
4
|
+
import { SimEventTargetRetryPolicy, } from "./sim-event-target-retry-policy.js";
|
|
3
5
|
import { SimEventTargetEcs, } from "./sim-event-target-ecs.js";
|
|
4
6
|
/**
|
|
5
7
|
* Real EventBridge allows alphanumerics, full stops, hyphens and underscores,
|
|
@@ -35,11 +37,26 @@ export class SimEventTarget {
|
|
|
35
37
|
* is what the task overrides instead.
|
|
36
38
|
*/
|
|
37
39
|
ecs;
|
|
40
|
+
/**
|
|
41
|
+
* How long and how often a failed delivery is retried, where the target
|
|
42
|
+
* says.
|
|
43
|
+
*
|
|
44
|
+
* A target without one is delivered once. Real EventBridge retries such a
|
|
45
|
+
* target for up to 24 hours by default, and that divergence is documented.
|
|
46
|
+
*/
|
|
47
|
+
retryPolicy;
|
|
48
|
+
/**
|
|
49
|
+
* The queue an event goes to once delivery is given up, where the target
|
|
50
|
+
* names one.
|
|
51
|
+
*/
|
|
52
|
+
deadLetterConfig;
|
|
38
53
|
constructor(properties) {
|
|
39
54
|
this.id = properties.id;
|
|
40
55
|
this.arn = properties.arn;
|
|
41
56
|
this.input = properties.input;
|
|
42
57
|
this.ecs = properties.ecs;
|
|
58
|
+
this.retryPolicy = properties.retryPolicy;
|
|
59
|
+
this.deadLetterConfig = properties.deadLetterConfig;
|
|
43
60
|
}
|
|
44
61
|
/**
|
|
45
62
|
* Read a target from request input.
|
|
@@ -51,6 +68,8 @@ export class SimEventTarget {
|
|
|
51
68
|
arn,
|
|
52
69
|
input: this.readInput(properties.Input),
|
|
53
70
|
ecs: SimEventTargetEcs.of(arn, properties),
|
|
71
|
+
retryPolicy: SimEventTargetRetryPolicy.optional(properties.RetryPolicy),
|
|
72
|
+
deadLetterConfig: SimEventTargetDeadLetterConfig.optional(properties.DeadLetterConfig),
|
|
54
73
|
});
|
|
55
74
|
}
|
|
56
75
|
/**
|
package/docs/serve/README.md
CHANGED
|
@@ -415,6 +415,6 @@ service guide lists its supported commands.
|
|
|
415
415
|
- `yulin watch` does not preserve simulated state across a restart or reload changed Lambda and
|
|
416
416
|
CloudFront Function code inside the current process.
|
|
417
417
|
- The shared AWS API endpoint refuses unsupported protocols and operations with `501 Not
|
|
418
|
-
Implemented`.
|
|
418
|
+
Implemented`.
|
|
419
419
|
- Some service functionality is available only through `SimAws` or SDK interception. Check the
|
|
420
420
|
relevant service guide before depending on access through the local endpoint.
|
|
@@ -948,8 +948,20 @@ console.log(
|
|
|
948
948
|
|
|
949
949
|
A parameter with no supplied value takes the template default, when the template has one.
|
|
950
950
|
|
|
951
|
-
A
|
|
952
|
-
|
|
951
|
+
A `CommaDelimitedList` or `List<...>` parameter (`List<String>`, `List<Number>`,
|
|
952
|
+
`List<AWS::EC2::Subnet::Id>` and the rest) is given one comma-separated string. A `Ref` to it
|
|
953
|
+
resolves to the list of members, each trimmed of the spaces around it. `Fn::Join` and `Fn::Select`
|
|
954
|
+
read that list as they read any other:
|
|
955
|
+
|
|
956
|
+
```json
|
|
957
|
+
{ "Fn::Join": ["-", { "Ref": "Names" }] }
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
With `Names` declared as a `CommaDelimitedList` and given `a, b, c`, this resolves to `a-b-c`. The
|
|
961
|
+
members of a `List<Number>` are strings, as CloudFormation gives them.
|
|
962
|
+
|
|
963
|
+
The `AWS::SSM::Parameter::Value<...>` types hold a Parameter Store name and resolve to the value
|
|
964
|
+
stored under it. See
|
|
953
965
|
[reading a parameter through a template Parameter](https://yulinsim.dev/services/ssm/#reading-a-parameter-through-a-template-parameter).
|
|
954
966
|
Every other type is accepted and its value used as written, with no validation of the value against
|
|
955
967
|
the type.
|
|
@@ -1217,6 +1229,17 @@ await simAws.cloudFormation().deployTemplate({
|
|
|
1217
1229
|
});
|
|
1218
1230
|
```
|
|
1219
1231
|
|
|
1232
|
+
The second argument may also be a function that returns the whole list. CDK writes this for
|
|
1233
|
+
`Fn.join(",", zone.hostedZoneNameServers)`:
|
|
1234
|
+
|
|
1235
|
+
```json
|
|
1236
|
+
{ "Fn::Join": [",", { "Fn::GetAtt": ["Zone", "NameServers"] }] }
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
`Fn::Split`, an `Fn::FindInMap` of a list value, `Fn::If` and a `Ref` to a list parameter can supply
|
|
1240
|
+
the list the same way. A list that resolves to anything but strings fails the deployment. That
|
|
1241
|
+
includes a number, and a list nested inside the list (CloudFormation joins one level only).
|
|
1242
|
+
|
|
1220
1243
|
### `Fn::Sub`
|
|
1221
1244
|
|
|
1222
1245
|
```typescript sim-cloudformation-fn-sub
|
|
@@ -4545,9 +4568,9 @@ Each service's own docs describe what its resource types support.
|
|
|
4545
4568
|
would reject as well. The simulator just rejects them later rather than up front.
|
|
4546
4569
|
- `Fn::If` is a condition function inside the `Conditions` section, and is not a value an
|
|
4547
4570
|
`Fn::Equals` can compare. Real CloudFormation allows only `Ref` and `Fn::FindInMap` there.
|
|
4548
|
-
- `Fn::Split` and `Fn::Select` accept any argument that resolves to the type they
|
|
4549
|
-
CloudFormation allows only a named set of functions inside each of them. A template the
|
|
4550
|
-
resolves may still be one CloudFormation rejects.
|
|
4571
|
+
- `Fn::Join`, `Fn::Split` and `Fn::Select` accept any argument that resolves to the type they
|
|
4572
|
+
need. Real CloudFormation allows only a named set of functions inside each of them. A template the
|
|
4573
|
+
simulator resolves may still be one CloudFormation rejects.
|
|
4551
4574
|
- The SAM transform is expanded for `AWS::Serverless::Function`, `AWS::Serverless::SimpleTable`,
|
|
4552
4575
|
`AWS::Serverless::HttpApi` and `AWS::Serverless::Api`. Every other `AWS::Serverless::*` resource
|
|
4553
4576
|
type is recorded as unsupported. `Api`, `HttpApi`, `SQS`, `DynamoDB`, `SNS`, `S3`, `Cognito`,
|
|
@@ -3940,7 +3940,7 @@ is written.
|
|
|
3940
3940
|
`AWS::DynamoDB::Table` path does, with the replica's `TableClass`, `DeletionProtectionEnabled` and
|
|
3941
3941
|
`Tags` read off it, the table's writes and the replica's reads put back together into one
|
|
3942
3942
|
provisioned capacity for the table and for each global secondary index, and `Ref`, `Fn::GetAtt …
|
|
3943
|
-
Arn`, `Fn::GetAtt … StreamArn` and `Fn::GetAtt … TableId` answering. A CDK `TableV2` stack deploys
|
|
3943
|
+
Arn`, `Fn::GetAtt … StreamArn` and `Fn::GetAtt … TableId` answering. A CDK `TableV2` stack deploys
|
|
3944
3944
|
through it without hand-editing.
|
|
3945
3945
|
- SDK interception, and an intercepted `DynamoDBClient` or `DynamoDBStreamsClient` reaches the
|
|
3946
3946
|
simulation.
|
|
@@ -4035,7 +4035,7 @@ Arn`, `Fn::GetAtt … StreamArn` and `Fn::GetAtt … TableId` answering. A CDK `
|
|
|
4035
4035
|
- Time to live expiry is dispatched by moving the clock through `simAws.clock()`, not by real time
|
|
4036
4036
|
elapsing. An item whose window goes by while a running-mode clock tracks the host stays where it
|
|
4037
4037
|
is until something moves the clock. A simulated DynamoDB constructed standalone as `new
|
|
4038
|
-
SimDynamoDb()` has no clock control at all. No item there ever expires.
|
|
4038
|
+
SimDynamoDb()` has no clock control at all. No item there ever expires.
|
|
4039
4039
|
- A Lambda event source mapping is the only simulated service integration that consumes a stream.
|
|
4040
4040
|
Anything else reads one through the Streams API itself. A Kinesis Data Streams destination is
|
|
4041
4041
|
absent.
|
|
@@ -921,6 +921,91 @@ and a rule routes the same events whether it carries them or not. They are recor
|
|
|
921
921
|
property and the deploy stands. Nothing reads them back. A rule or a bus deployed with tags behaves
|
|
922
922
|
as though the template had never named them.
|
|
923
923
|
|
|
924
|
+
## Receiving events from a SaaS partner
|
|
925
|
+
|
|
926
|
+
A SaaS partner such as Stripe sends events to an account through a partner event source, named like
|
|
927
|
+
`aws.partner/stripe.com/ed_...`. The partner creates the source from its own account, so a test
|
|
928
|
+
shares one with `addPartnerEventSource(...)`. The account then creates a partner event bus with the
|
|
929
|
+
same `Name` and `EventSourceName`, and `putPartnerEvents(...)` sends events onto it as the partner
|
|
930
|
+
would.
|
|
931
|
+
|
|
932
|
+
```typescript sim-event-bridge-partner-events
|
|
933
|
+
/**
|
|
934
|
+
* Receiving Stripe's events on a partner event bus.
|
|
935
|
+
*/
|
|
936
|
+
|
|
937
|
+
import {
|
|
938
|
+
CreateEventBusCommand,
|
|
939
|
+
PutPartnerEventsCommand,
|
|
940
|
+
PutRuleCommand,
|
|
941
|
+
} from "@aws-sdk/client-eventbridge";
|
|
942
|
+
|
|
943
|
+
import { SimAws } from "@kensio/yulin";
|
|
944
|
+
|
|
945
|
+
const simAws = new SimAws();
|
|
946
|
+
const events = simAws.eventBridge();
|
|
947
|
+
const source = "aws.partner/stripe.com/ed_test_billing";
|
|
948
|
+
|
|
949
|
+
// What Stripe does when an event destination is set up for the account.
|
|
950
|
+
events.addPartnerEventSource(source);
|
|
951
|
+
|
|
952
|
+
// What the account does to receive from it.
|
|
953
|
+
await events.createEventBus(
|
|
954
|
+
new CreateEventBusCommand({ Name: source, EventSourceName: source }),
|
|
955
|
+
);
|
|
956
|
+
await events.putRule(
|
|
957
|
+
new PutRuleCommand({
|
|
958
|
+
Name: "subscriptions",
|
|
959
|
+
EventBusName: source,
|
|
960
|
+
EventPattern: JSON.stringify({
|
|
961
|
+
source: [{ prefix: "aws.partner/stripe.com" }],
|
|
962
|
+
"detail-type": ["customer.subscription.created"],
|
|
963
|
+
}),
|
|
964
|
+
}),
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
// What Stripe sends when a subscription starts.
|
|
968
|
+
await events.putPartnerEvents(
|
|
969
|
+
new PutPartnerEventsCommand({
|
|
970
|
+
Entries: [
|
|
971
|
+
{
|
|
972
|
+
Source: source,
|
|
973
|
+
DetailType: "customer.subscription.created",
|
|
974
|
+
Detail: JSON.stringify({
|
|
975
|
+
id: "evt_test_subscription",
|
|
976
|
+
type: "customer.subscription.created",
|
|
977
|
+
data: { object: { id: "sub_test" } },
|
|
978
|
+
}),
|
|
979
|
+
},
|
|
980
|
+
],
|
|
981
|
+
}),
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
console.log(events.receiptsOn(source)[0]?.matchedRuleNames); // ["subscriptions"]
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
`putPartnerEvents(...)` takes the entries of the partner's `PutPartnerEvents` request. Each entry's
|
|
988
|
+
`Source` names a shared source, and the event goes to the bus of the same name. Rules match it on
|
|
989
|
+
`source`, `detail-type` and `detail` like any other event. A target receives the usual envelope, with
|
|
990
|
+
`account` set to the receiving account. Stripe puts its event type in `DetailType` and the whole
|
|
991
|
+
Stripe event object, as JSON, in `Detail`. An entry whose `Source` names no shared source fails the
|
|
992
|
+
whole request with `ResourceNotFoundException`.
|
|
993
|
+
|
|
994
|
+
An `AWS::Events::EventBus` with `Name` and `EventSourceName` both set to the source name creates the
|
|
995
|
+
same bus from a template, and a rule names it with a `Ref` to the bus.
|
|
996
|
+
|
|
997
|
+
The source has to be shared before the bus is created. `CreateEventBus` fails with
|
|
998
|
+
`ResourceNotFoundException` when it is missing, and a template creating the bus fails its stack, as
|
|
999
|
+
both do on AWS. A `Name` that differs from the `EventSourceName` is a `ValidationException`, as is a
|
|
1000
|
+
`/` in the name of a bus created without one.
|
|
1001
|
+
|
|
1002
|
+
`DescribeEventSource` reports the source as `PENDING` until its bus exists, and `ACTIVE` after.
|
|
1003
|
+
Deleting the bus puts it back to `PENDING`. An event sent while the source is pending is dropped,
|
|
1004
|
+
as AWS documents.
|
|
1005
|
+
|
|
1006
|
+
Only the partner sends events to a partner event bus. `PutEvents` naming one is refused with a
|
|
1007
|
+
`ValidationException` (its `EventBusName` takes no `/`).
|
|
1008
|
+
|
|
924
1009
|
## Reading back a failed delivery
|
|
925
1010
|
|
|
926
1011
|
Real EventBridge tells the caller nothing about a failed delivery. A `PutEvents` that matched a rule
|
|
@@ -981,6 +1066,125 @@ no is a modelled outcome a test may be asking for on purpose.
|
|
|
981
1066
|
`JSON.stringify` on a failure carries the message alongside the rule, the target and the event it
|
|
982
1067
|
names.
|
|
983
1068
|
|
|
1069
|
+
## Retrying and dead-lettering a delivery
|
|
1070
|
+
|
|
1071
|
+
A target can carry a `RetryPolicy` and a `DeadLetterConfig`, from `PutTargets` or from a target in an
|
|
1072
|
+
`AWS::Events::Rule`. The dead-letter queue receives an event once EventBridge gives up delivering it.
|
|
1073
|
+
|
|
1074
|
+
```typescript sim-event-bridge-dead-letter
|
|
1075
|
+
/**
|
|
1076
|
+
* Sending an event a target refused to its dead-letter queue.
|
|
1077
|
+
*/
|
|
1078
|
+
|
|
1079
|
+
import {
|
|
1080
|
+
PutEventsCommand,
|
|
1081
|
+
PutRuleCommand,
|
|
1082
|
+
PutTargetsCommand,
|
|
1083
|
+
} from "@aws-sdk/client-eventbridge";
|
|
1084
|
+
import {
|
|
1085
|
+
CreateQueueCommand,
|
|
1086
|
+
ReceiveMessageCommand,
|
|
1087
|
+
SetQueueAttributesCommand,
|
|
1088
|
+
} from "@aws-sdk/client-sqs";
|
|
1089
|
+
|
|
1090
|
+
import { SimAws } from "@kensio/yulin";
|
|
1091
|
+
|
|
1092
|
+
const simAws = new SimAws();
|
|
1093
|
+
const dlqArn = "arn:aws:sqs:us-east-1:888888888888:undelivered-orders";
|
|
1094
|
+
|
|
1095
|
+
// A dead-letter queue admitting EventBridge for the rule.
|
|
1096
|
+
const { QueueUrl } = await simAws
|
|
1097
|
+
.sqs()
|
|
1098
|
+
.createQueue(new CreateQueueCommand({ QueueName: "undelivered-orders" }));
|
|
1099
|
+
await simAws.sqs().setQueueAttributes(
|
|
1100
|
+
new SetQueueAttributesCommand({
|
|
1101
|
+
QueueUrl,
|
|
1102
|
+
Attributes: {
|
|
1103
|
+
Policy: JSON.stringify({
|
|
1104
|
+
Version: "2012-10-17",
|
|
1105
|
+
Statement: [
|
|
1106
|
+
{
|
|
1107
|
+
Effect: "Allow",
|
|
1108
|
+
Principal: { Service: "events.amazonaws.com" },
|
|
1109
|
+
Action: "sqs:SendMessage",
|
|
1110
|
+
Resource: dlqArn,
|
|
1111
|
+
Condition: {
|
|
1112
|
+
ArnEquals: {
|
|
1113
|
+
"aws:SourceArn":
|
|
1114
|
+
"arn:aws:events:us-east-1:888888888888:rule/orders",
|
|
1115
|
+
},
|
|
1116
|
+
},
|
|
1117
|
+
},
|
|
1118
|
+
],
|
|
1119
|
+
}),
|
|
1120
|
+
},
|
|
1121
|
+
}),
|
|
1122
|
+
);
|
|
1123
|
+
|
|
1124
|
+
// A target queue that was never created, so every delivery fails.
|
|
1125
|
+
await simAws.eventBridge().putRule(
|
|
1126
|
+
new PutRuleCommand({
|
|
1127
|
+
Name: "orders",
|
|
1128
|
+
EventPattern: JSON.stringify({ source: ["orders.service"] }),
|
|
1129
|
+
}),
|
|
1130
|
+
);
|
|
1131
|
+
await simAws.eventBridge().putTargets(
|
|
1132
|
+
new PutTargetsCommand({
|
|
1133
|
+
Rule: "orders",
|
|
1134
|
+
Targets: [
|
|
1135
|
+
{
|
|
1136
|
+
Id: "fulfilment",
|
|
1137
|
+
Arn: "arn:aws:sqs:us-east-1:888888888888:fulfilment",
|
|
1138
|
+
RetryPolicy: { MaximumRetryAttempts: 2 },
|
|
1139
|
+
DeadLetterConfig: { Arn: dlqArn },
|
|
1140
|
+
},
|
|
1141
|
+
],
|
|
1142
|
+
}),
|
|
1143
|
+
);
|
|
1144
|
+
|
|
1145
|
+
await simAws.eventBridge().putEvents(
|
|
1146
|
+
new PutEventsCommand({
|
|
1147
|
+
Entries: [
|
|
1148
|
+
{ Source: "orders.service", DetailType: "OrderPlaced", Detail: "{}" },
|
|
1149
|
+
],
|
|
1150
|
+
}),
|
|
1151
|
+
);
|
|
1152
|
+
await simAws.backgroundTasksComplete();
|
|
1153
|
+
|
|
1154
|
+
const { Messages } = await simAws
|
|
1155
|
+
.sqs()
|
|
1156
|
+
.receiveMessage(
|
|
1157
|
+
new ReceiveMessageCommand({ QueueUrl, MessageAttributeNames: ["All"] }),
|
|
1158
|
+
);
|
|
1159
|
+
|
|
1160
|
+
console.log(Messages?.[0]?.MessageAttributes?.["ERROR_CODE"]?.StringValue);
|
|
1161
|
+
// "NO_RESOURCE"
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
The message body is the event, as JSON. Its attributes are the ones EventBridge documents.
|
|
1165
|
+
`RULE_ARN` and `TARGET_ARN` name where the event was going. `ERROR_CODE` and `ERROR_MESSAGE` say why
|
|
1166
|
+
it failed, and `RETRY_ATTEMPTS` counts the retries made. `EXHAUSTED_RETRY_CONDITION` is
|
|
1167
|
+
`MaximumRetryAttempts` or `MaximumEventAgeInSeconds` when a retry limit ran out.
|
|
1168
|
+
|
|
1169
|
+
`ERROR_CODE` is `NO_PERMISSIONS` for a target that refused EventBridge and `NO_RESOURCE` for one
|
|
1170
|
+
that is not there. Every other failure is `ERROR_FROM_TARGET`. EventBridge lists these codes
|
|
1171
|
+
without saying which failure gets which.
|
|
1172
|
+
|
|
1173
|
+
A missing target and a refusal are never retried, because the same request gets the same answer.
|
|
1174
|
+
EventBridge sends both straight to the dead-letter queue, and so does Yulin. Any other failure is
|
|
1175
|
+
retried on the simulation's clock. The first retry is due one second after the failed attempt, and
|
|
1176
|
+
each following wait doubles to 2, 4, 8 seconds and so on. Retries stop at `MaximumRetryAttempts`, or
|
|
1177
|
+
once the event is `MaximumEventAgeInSeconds` old. A retry only runs as `advanceBy(...)` moves the
|
|
1178
|
+
clock past it.
|
|
1179
|
+
|
|
1180
|
+
EventBridge sends to the dead-letter queue as `events.amazonaws.com`, with the rule ARN as
|
|
1181
|
+
`aws:SourceArn`, so the queue policy has to admit it. A dead-letter queue that is missing or refuses
|
|
1182
|
+
EventBridge leaves the failure in `deliveryFailures`. An event that reached its dead-letter queue
|
|
1183
|
+
leaves nothing there.
|
|
1184
|
+
|
|
1185
|
+
A Lambda target is invoked asynchronously. Once Lambda accepts the invocation the delivery is done,
|
|
1186
|
+
and a handler error is left to the function's own retries and destinations.
|
|
1187
|
+
|
|
984
1188
|
## Permissions
|
|
985
1189
|
|
|
986
1190
|
Most operations are authorized by simulated IAM against the bus ARN. The two that name no bus
|
|
@@ -1048,6 +1252,8 @@ no permission for.
|
|
|
1048
1252
|
## Supported operations
|
|
1049
1253
|
|
|
1050
1254
|
- `CreateEventBus`, `DeleteEventBus`, `DescribeEventBus`, `ListEventBuses` and `PutEvents`.
|
|
1255
|
+
- Partner event buses created with `EventSourceName`, and `DescribeEventSource`. A test acts as the
|
|
1256
|
+
partner through `addPartnerEventSource(...)` and `putPartnerEvents(...)`.
|
|
1051
1257
|
- `PutRule`, `DeleteRule`, `DescribeRule`, `ListRules`, `EnableRule`, `DisableRule` and
|
|
1052
1258
|
`TestEventPattern`.
|
|
1053
1259
|
- Scheduled rules, with a `rate(...)` or six-field `cron(...)` `ScheduleExpression`, fired by
|
|
@@ -1061,6 +1267,8 @@ no permission for.
|
|
|
1061
1267
|
- Targets in another account or region of the same simulation, admitted by the target's own resource
|
|
1062
1268
|
policy on `aws:SourceArn` or `aws:SourceAccount`, as real EventBridge does.
|
|
1063
1269
|
- A target's fixed `Input`, and `deliveryFailures` for a delivery that failed.
|
|
1270
|
+
- A target's `RetryPolicy`, retried on the simulation's clock, and its `DeadLetterConfig`, with the
|
|
1271
|
+
dead-letter message attributes EventBridge documents.
|
|
1064
1272
|
- The `default` bus in every account and region, without one being created.
|
|
1065
1273
|
- Bus descriptions, creation timestamps from the simulation's clock, and prefix-narrowed paged
|
|
1066
1274
|
listings.
|
|
@@ -1073,9 +1281,13 @@ no permission for.
|
|
|
1073
1281
|
|
|
1074
1282
|
- Targets deliver to Lambda, SQS and SNS, and run a task in ECS. A target ARN naming any other
|
|
1075
1283
|
service is refused as the target is added, ahead of any matching event.
|
|
1076
|
-
- Target `InputPath` and `InputTransformer` are refused
|
|
1077
|
-
|
|
1078
|
-
|
|
1284
|
+
- Target `InputPath` and `InputTransformer` are refused. A target `RoleArn` is refused except on an
|
|
1285
|
+
ECS target. That is the one target type that runs as a role, where the others run as the service
|
|
1286
|
+
principal.
|
|
1287
|
+
- A target with no `RetryPolicy` is delivered once. Real EventBridge retries such a target for up to
|
|
1288
|
+
24 hours and 185 times. Retry waits are deterministic powers of two seconds, where real
|
|
1289
|
+
EventBridge uses exponential backoff with jitter. The fixed sequence lets a test move the clock to
|
|
1290
|
+
a known retry.
|
|
1079
1291
|
- An ECS target's `EcsParameters` takes `TaskDefinitionArn` and `TaskCount`, and takes and ignores
|
|
1080
1292
|
`LaunchType`, `PlatformVersion`, `NetworkConfiguration` and `CapacityProviderStrategy`, since
|
|
1081
1293
|
there is no placement and no network here for them to apply to. Anything else it can carry, such
|
|
@@ -1115,8 +1327,13 @@ no permission for.
|
|
|
1115
1327
|
attribute are all missing, and a caller from another account cannot be admitted to a bus. That is
|
|
1116
1328
|
stricter than real AWS.
|
|
1117
1329
|
- Putting an event onto another account's or region's bus is refused.
|
|
1118
|
-
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1330
|
+
- Event bus tags, encryption with a customer managed key, dead letter queues, logging configuration
|
|
1331
|
+
and global endpoints are refused. An `AWS::Events::EventBus` carrying `Tags` deploys with the tags
|
|
1332
|
+
dropped and the property recorded.
|
|
1333
|
+
- A pending partner event source never expires, and `DescribeEventSource` leaves out
|
|
1334
|
+
`ExpirationTime`. Its `CreatedBy` is the segment after `aws.partner/`, such as `stripe.com`.
|
|
1335
|
+
`ListEventSources`, `ActivateEventSource` and `DeactivateEventSource` are absent, as are the
|
|
1336
|
+
partner's own commands. A partner is a test calling `addPartnerEventSource(...)` and
|
|
1337
|
+
`putPartnerEvents(...)`.
|
|
1121
1338
|
- Archives, replay, schema registry and discovery, API destinations and connections are not
|
|
1122
1339
|
simulated.
|
|
@@ -1079,7 +1079,7 @@ A delete on a versioned Bucket raises `s3:ObjectRemoved:DeleteMarkerCreated` rat
|
|
|
1079
1079
|
|
|
1080
1080
|
- MFA delete is refused with `NotImplemented` rather than stored. Nothing here could enforce it, and
|
|
1081
1081
|
a Bucket reporting a protection it does not apply is worse than one that says so. `MFADelete:
|
|
1082
|
-
"Disabled"` is taken, and any other value is refused with `InvalidArgument`.
|
|
1082
|
+
"Disabled"` is taken, and any other value is refused with `InvalidArgument`.
|
|
1083
1083
|
- A `versionId` in a `CopySource` is still refused with `NotImplemented`. A copy reads the current
|
|
1084
1084
|
version.
|
|
1085
1085
|
- `NoncurrentVersionTransitions` is stored and unread, because storage classes are left out. An
|
|
@@ -1214,7 +1214,7 @@ Current documented limitations:
|
|
|
1214
1214
|
- A Lambda event source mapping polls one batch at a time. Real Lambda runs several pollers at once
|
|
1215
1215
|
and scales them with the queue, and what that concurrency does to ordering is invisible here. See
|
|
1216
1216
|
[simulated Lambda](https://yulinsim.dev/services/lambda/#triggering-a-function-from-an-sqs-queue "Simulated Lambda event
|
|
1217
|
-
source mapping docs") for the rest of the mapping limitations.
|
|
1217
|
+
source mapping docs") for the rest of the mapping limitations.
|
|
1218
1218
|
- `AWS::SQS::Queue` and `AWS::SQS::QueuePolicy` are the SQS resource types CloudFormation creates.
|
|
1219
1219
|
Any other is reported as unsupported and skipped. A queue attribute outside the range real SQS
|
|
1220
1220
|
accepts fails the resource, and a property it has no behaviour for is recorded and the queue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kensio/yulin",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.28",
|
|
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/",
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
"hyparquet": "^1.29.2",
|
|
300
300
|
"hyparquet-writer": "^0.16.9",
|
|
301
301
|
"node-sql-parser": "^5.4.0",
|
|
302
|
-
"oxfmt": "^0.
|
|
302
|
+
"oxfmt": "^0.72.0",
|
|
303
303
|
"oxlint": "^1.77.0",
|
|
304
304
|
"oxlint-tsgolint": "^7.0.2001",
|
|
305
305
|
"semantic-release": "25.0.9",
|