@kensio/yulin 1.21.6 → 1.21.8
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/README.md +22 -2
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-creator.js +1 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.d.ts +4 -0
- package/dist/service/eventbridge/cfn/bus/sim-cfn-event-bus-properties.js +26 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-creator.js +3 -1
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-properties.d.ts +0 -7
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-properties.js +0 -20
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-unsimulated-properties.d.ts +13 -0
- package/dist/service/eventbridge/cfn/rule/sim-cfn-event-rule-unsimulated-properties.js +59 -0
- package/dist/service/eventbridge/cfn/sim-cfn-event-bridge-resource-error.d.ts +1 -1
- package/dist/service/eventbridge/cfn/sim-cfn-event-bridge-resource-error.js +1 -1
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-properties.js +1 -1
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.d.ts +3 -2
- package/dist/service/lambda/cfn/event-source-mapping/sim-cfn-lambda-event-source-mapping-property-rules.js +25 -3
- package/dist/service/ses/command/authorize/sim-ses-authorizer.d.ts +9 -0
- package/dist/service/ses/command/authorize/sim-ses-authorizer.js +18 -2
- package/dist/service/ses/command/send/sim-ses-send-email.js +2 -1
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-creator.js +1 -0
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-properties.d.ts +9 -4
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-properties.js +18 -6
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-property-names.d.ts +10 -0
- package/dist/service/sns/cfn/topic/sim-cfn-sns-topic-property-names.js +16 -1
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-creator.js +1 -1
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.d.ts +11 -6
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.js +18 -9
- package/docs/README.md +40 -4
- package/docs/ai-skill/README.md +57 -54
- package/docs/cli/README.md +84 -94
- package/docs/factories/README.md +42 -54
- package/docs/lint/README.md +41 -67
- package/docs/non-aws-dependencies/README.md +72 -168
- package/docs/sdk/README.md +109 -95
- package/docs/serve/README.md +192 -898
- package/docs/services/acm/README.md +24 -40
- package/docs/services/apigateway/README.md +52 -71
- package/docs/services/apigatewayv2/README.md +55 -74
- package/docs/services/athena/README.md +17 -26
- package/docs/services/backup/README.md +29 -39
- package/docs/services/bedrock/README.md +38 -52
- package/docs/services/cloudformation/README.md +43 -55
- package/docs/services/cloudfront/README.md +69 -95
- package/docs/services/cloudwatch/README.md +40 -54
- package/docs/services/cognito/README.md +30 -45
- package/docs/services/dynamodb/README.md +34 -51
- package/docs/services/ecr/README.md +36 -77
- package/docs/services/ecs/README.md +26 -46
- package/docs/services/elbv2/README.md +19 -29
- package/docs/services/eventbridge/README.md +24 -20
- package/docs/services/firehose/README.md +24 -32
- package/docs/services/glue/README.md +41 -78
- package/docs/services/iam/README.md +13 -15
- package/docs/services/kinesis/README.md +53 -93
- package/docs/services/kms/README.md +22 -32
- package/docs/services/lambda/README.md +60 -80
- package/docs/services/logs/README.md +41 -50
- package/docs/services/organizations/README.md +50 -85
- package/docs/services/personalize/README.md +28 -44
- package/docs/services/rekognition/README.md +26 -38
- package/docs/services/route53/README.md +17 -17
- package/docs/services/s3/README.md +47 -51
- package/docs/services/scheduler/README.md +41 -52
- package/docs/services/secretsmanager/README.md +27 -42
- package/docs/services/ses/README.md +24 -34
- package/docs/services/sns/README.md +31 -33
- package/docs/services/sqs/README.md +14 -14
- package/docs/services/ssm/README.md +19 -21
- package/docs/services/stepfunctions/README.md +18 -20
- package/docs/services/sts/README.md +32 -45
- package/docs/services/wafv2/README.md +12 -17
- package/docs/terraform/README.md +108 -126
- package/docs/testing/README.md +228 -0
- package/docs/time/README.md +87 -117
- package/llms.txt +2 -1
- package/package.json +1 -1
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
# Simulated KMS
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Node.js's own `crypto`. A ciphertext can only be read with its key, and a decryption with the wrong
|
|
7
|
-
encryption context fails.
|
|
3
|
+
Yulin simulates AWS Key Management Service (KMS) in memory. Symmetric keys use AES-256 key material,
|
|
4
|
+
and asymmetric keys use real key pairs. Cryptographic operations run through Node.js `crypto`, so
|
|
5
|
+
the wrong key or encryption context cannot decrypt a ciphertext.
|
|
8
6
|
|
|
9
7
|
KMS-specific types are imported from the `@kensio/yulin/kms` subpath.
|
|
10
8
|
|
|
11
9
|
## Encrypting and decrypting
|
|
12
10
|
|
|
13
|
-
Create a key
|
|
14
|
-
|
|
11
|
+
Create a key, encrypt a value, then decrypt it. `Decrypt` does not need a `KeyId` for symmetric
|
|
12
|
+
ciphertext because the ciphertext identifies its key.
|
|
15
13
|
|
|
16
14
|
```typescript sim-kms-encrypt-decrypt
|
|
17
15
|
/**
|
|
@@ -52,8 +50,8 @@ any second `SimAws` instance both reject it.
|
|
|
52
50
|
|
|
53
51
|
## Encryption context
|
|
54
52
|
|
|
55
|
-
An encryption context
|
|
56
|
-
|
|
53
|
+
An encryption context binds non-secret key/value data to a ciphertext. Decryption requires the same
|
|
54
|
+
context.
|
|
57
55
|
|
|
58
56
|
```typescript sim-kms-encryption-context
|
|
59
57
|
/**
|
|
@@ -100,9 +98,8 @@ The context is an unordered map. The same pairs written in a different order sti
|
|
|
100
98
|
|
|
101
99
|
## Envelope encryption
|
|
102
100
|
|
|
103
|
-
`Encrypt`
|
|
104
|
-
|
|
105
|
-
encrypted under the KMS key to store alongside it.
|
|
101
|
+
`Encrypt` accepts at most 4,096 bytes. For larger values, use `GenerateDataKey`. It returns a
|
|
102
|
+
plaintext data key for encryption and an encrypted copy to store with the data.
|
|
106
103
|
|
|
107
104
|
```typescript sim-kms-generate-data-key
|
|
108
105
|
/**
|
|
@@ -141,8 +138,8 @@ console.log(recovered.Plaintext?.length); // 32
|
|
|
141
138
|
|
|
142
139
|
## Signing and verifying
|
|
143
140
|
|
|
144
|
-
A key
|
|
145
|
-
|
|
141
|
+
A key with `KeyUsage: SIGN_VERIFY` holds a real key pair. Set a signing key spec because the default
|
|
142
|
+
`SYMMETRIC_DEFAULT` key cannot sign.
|
|
146
143
|
|
|
147
144
|
```typescript sim-kms-sign-verify
|
|
148
145
|
/**
|
|
@@ -261,9 +258,8 @@ both matching what KMS produces. `GetPublicKey` against a symmetric key is
|
|
|
261
258
|
|
|
262
259
|
## Key policies and IAM
|
|
263
260
|
|
|
264
|
-
Every
|
|
265
|
-
|
|
266
|
-
needed:
|
|
261
|
+
Every key has a key policy. An identity policy granting `kms:Decrypt` works only when the key policy
|
|
262
|
+
also permits the caller:
|
|
267
263
|
|
|
268
264
|
- A statement naming the caller grants access outright. A role with no permissions of its own can
|
|
269
265
|
still use the key.
|
|
@@ -342,16 +338,15 @@ on real KMS.
|
|
|
342
338
|
|
|
343
339
|
## AWS managed keys and `kms:ViaService`
|
|
344
340
|
|
|
345
|
-
An alias beginning `alias/aws/` names an AWS managed key
|
|
346
|
-
|
|
347
|
-
customer default:
|
|
341
|
+
An alias beginning with `alias/aws/` names an AWS managed key. Yulin creates that key when it is
|
|
342
|
+
first referenced and applies AWS-managed-key policy behavior:
|
|
348
343
|
|
|
349
344
|
- Use of the key is allowed to any principal in the owning account, but only when `kms:ViaService`
|
|
350
345
|
names the service that owns the key, such as `ssm.us-east-1.amazonaws.com` for `aws/ssm`.
|
|
351
|
-
- The account root
|
|
352
|
-
delegates to IAM.
|
|
346
|
+
- The account root can read the key's metadata.
|
|
353
347
|
|
|
354
|
-
|
|
348
|
+
A role cannot use an AWS managed key by calling KMS directly, even when its identity policy grants
|
|
349
|
+
`kms:Decrypt`.
|
|
355
350
|
|
|
356
351
|
`kms:ViaService` is set by the service making the call on the caller's behalf. Sim SSM does this for
|
|
357
352
|
`SecureString` parameters. Code calling simulated KMS directly sets it with the `viaService` request
|
|
@@ -417,8 +412,7 @@ and a condition on it stays unmatched.
|
|
|
417
412
|
|
|
418
413
|
## Naming a key
|
|
419
414
|
|
|
420
|
-
|
|
421
|
-
a key ID, a key ARN, an alias name such as `alias/app-key`, and an alias ARN.
|
|
415
|
+
`KeyId` accepts a key ID, key ARN, alias name such as `alias/app-key`, or alias ARN.
|
|
422
416
|
|
|
423
417
|
A key ARN or alias ARN naming another account or region resolves to no key at all. Its identifier is
|
|
424
418
|
never read out and looked up locally. A foreign ARN cannot reach a key that happens to share an
|
|
@@ -473,8 +467,8 @@ console.log(managed.KeyMetadata?.KeyManager); // "AWS"
|
|
|
473
467
|
|
|
474
468
|
A key can be disabled and re-enabled later. A disabled key stays present, and refuses to be used.
|
|
475
469
|
|
|
476
|
-
|
|
477
|
-
|
|
470
|
+
`ScheduleKeyDeletion` sets a recovery window from 7 to 30 days, defaulting to 30. During that window
|
|
471
|
+
the key cannot be used but can be recovered with
|
|
478
472
|
`CancelKeyDeletion`. Cancelling leaves the key disabled. Re-enabling it is a separate step.
|
|
479
473
|
|
|
480
474
|
A disabled key fails cryptographic operations with `DisabledException`. A key pending deletion fails
|
|
@@ -600,9 +594,7 @@ the function's execution role as the caller. A handler that decrypts a value the
|
|
|
600
594
|
allowed to, by both the key policy and the role's identity policy, the same as on real AWS. See
|
|
601
595
|
[simulated Lambda](https://yulinsim.dev/services/lambda/) for how function code and execution roles work.
|
|
602
596
|
|
|
603
|
-
##
|
|
604
|
-
|
|
605
|
-
Sim KMS currently supports:
|
|
597
|
+
## Supported operations
|
|
606
598
|
|
|
607
599
|
- `CreateKeyCommand`, for symmetric encryption keys and asymmetric signing keys
|
|
608
600
|
- `DescribeKeyCommand` and `ListKeysCommand`
|
|
@@ -619,8 +611,6 @@ Sim KMS currently supports:
|
|
|
619
611
|
|
|
620
612
|
## Limitations
|
|
621
613
|
|
|
622
|
-
Current documented limitations:
|
|
623
|
-
|
|
624
614
|
- Only encryption with a symmetric key and signing with an asymmetric key are simulated. Left out
|
|
625
615
|
are asymmetric encryption (`RSAES_OAEP_SHA_1` and `RSAES_OAEP_SHA_256`), HMAC keys and
|
|
626
616
|
`GENERATE_VERIFY_MAC`, key agreement and `DeriveSharedSecret`, the `SM2` key spec, and
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Simulated Lambda
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
3
|
+
Yulin creates and invokes Lambda functions in process. A function can use an in-process handler,
|
|
4
|
+
code from a zip archive, code stored in simulated S3, or a handler bound to a container image.
|
|
5
5
|
|
|
6
6
|
Handlers run with their execution role as the simulated caller, so AWS calls made inside a handler
|
|
7
7
|
are authorized by simulated IAM, as on real Lambda. Creating a function and changing its role are
|
|
@@ -9,16 +9,14 @@ authorized as well, both against `lambda:` actions and against `iam:PassRole` on
|
|
|
9
9
|
the request names. See [passing a Role to a service](https://yulinsim.dev/services/iam/#passing-a-role-to-a-service)
|
|
10
10
|
in the IAM docs.
|
|
11
11
|
|
|
12
|
-
Lambda
|
|
13
|
-
instances can be routed into sim Lambda with
|
|
12
|
+
Lambda helpers are available from `@kensio/yulin/lambda`. A `LambdaClient` can be routed to Yulin with
|
|
14
13
|
[SDK interception](https://yulinsim.dev/sdk/ "Simulated AWS SDK interception docs").
|
|
15
14
|
|
|
16
15
|
## Creating and invoking a function
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
state.
|
|
17
|
+
Use `makeLambdaZipFileInput(...)` to pass an in-process handler through the SDK-shaped `Code.ZipFile`
|
|
18
|
+
input. The handler runs as an ordinary function in the Node.js process. It supports breakpoints and
|
|
19
|
+
access to local state.
|
|
22
20
|
|
|
23
21
|
```typescript sim-lambda-create-and-invoke
|
|
24
22
|
/**
|
|
@@ -84,18 +82,13 @@ The invoke call itself returns normally.
|
|
|
84
82
|
|
|
85
83
|
## Zip-packaged code and the vm runtime
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Run the packaged code where the test is about the bundle a deployment ships, its imports and its
|
|
91
|
-
bundling included. Both paths invoke through simulated Lambda, and simulated IAM authorizes the
|
|
92
|
-
handler's own AWS calls under the execution role either way.
|
|
85
|
+
Use an in-process handler for most tests. Use packaged code when the test covers the deployed bundle,
|
|
86
|
+
including its imports. Both forms run through simulated Lambda and make AWS calls as the function's
|
|
87
|
+
execution role.
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
real cold-start semantics. The module is imported once, on first invocation, and module state stays
|
|
98
|
-
warm across invocations.
|
|
89
|
+
`makeLambdaCodeZip(...)` builds zip bytes from a source string or a map of archive paths to file
|
|
90
|
+
contents. A source string becomes `index.js`. Yulin runs the archive in a Node.js `vm`, loads the
|
|
91
|
+
module on the first invocation and preserves module state for later invocations.
|
|
99
92
|
|
|
100
93
|
```typescript sim-lambda-zip-code-vm-runtime
|
|
101
94
|
/**
|
|
@@ -171,18 +164,15 @@ package is refused at cold start. A handler file ending in `.mjs` is reported as
|
|
|
171
164
|
Real Lambda has run ES module packages since nodejs14.x, and `NodejsFunction` in CDK emits one
|
|
172
165
|
under `format: OutputFormat.ESM`.
|
|
173
166
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
needs nothing further. Where the archive itself has to be the deployed artefact, compile a CommonJS
|
|
178
|
-
build of the same source and deploy that as the function's code.
|
|
167
|
+
Use an [executable binding](#executable-bindings) or `makeLambdaZipFileInput(...)` for an ESM handler.
|
|
168
|
+
The test's module system loads an in-process handler. To test the archive itself, compile the source
|
|
169
|
+
to CommonJS before creating the zip.
|
|
179
170
|
|
|
180
171
|
`Code.ZipFile` bytes that fail to unzip are rejected at creation with the AWS-like
|
|
181
172
|
`InvalidParameterValueException: Could not unzip uploaded file`.
|
|
182
173
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
unzipped normally.
|
|
174
|
+
`Code.ZipFile` accepts zip archives produced by other tools. Archives from `makeLambdaCodeZip` can
|
|
175
|
+
also be opened with standard zip tools.
|
|
186
176
|
|
|
187
177
|
### What a handler prints
|
|
188
178
|
|
|
@@ -408,9 +398,8 @@ writes none of those.
|
|
|
408
398
|
|
|
409
399
|
## Function code from S3
|
|
410
400
|
|
|
411
|
-
Function code
|
|
412
|
-
|
|
413
|
-
simulated IAM applies to the code object read.
|
|
401
|
+
Function code may reference a zip object in simulated S3. Yulin reads the object once during
|
|
402
|
+
function creation as the caller creating the function, so simulated IAM applies to the S3 read.
|
|
414
403
|
|
|
415
404
|
```typescript sim-lambda-s3-code
|
|
416
405
|
/**
|
|
@@ -944,10 +933,9 @@ the operation header that says so.
|
|
|
944
933
|
|
|
945
934
|
## Invocation types
|
|
946
935
|
|
|
947
|
-
`InvokeCommand` supports
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
handler at all.
|
|
936
|
+
`InvokeCommand` supports all three invocation types. `RequestResponse` waits for the handler and
|
|
937
|
+
returns its JSON result. `Event` returns 202 and schedules the handler in the background. `DryRun`
|
|
938
|
+
returns 204 without invoking the handler.
|
|
951
939
|
|
|
952
940
|
```typescript sim-lambda-invocation-types
|
|
953
941
|
/**
|
|
@@ -1007,14 +995,12 @@ covers.
|
|
|
1007
995
|
|
|
1008
996
|
## Asynchronous retries and destinations
|
|
1009
997
|
|
|
1010
|
-
An `Event` invocation
|
|
1011
|
-
|
|
1012
|
-
reaches them by advancing time rather than by waiting for it.
|
|
998
|
+
An `Event` invocation retries a failed handler twice by default. Retries use the simulated clock,
|
|
999
|
+
after about one minute and then two minutes. Advance the clock to run them in a test.
|
|
1013
1000
|
|
|
1014
|
-
`PutFunctionEventInvokeConfigCommand`
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
SNS topic, EventBridge event bus or Lambda function.
|
|
1001
|
+
`PutFunctionEventInvokeConfigCommand` controls retry count and destinations. Lambda sends a final
|
|
1002
|
+
failure to `OnFailure` and a successful result to `OnSuccess`. Destinations may be SQS, SNS,
|
|
1003
|
+
EventBridge or another Lambda function.
|
|
1018
1004
|
|
|
1019
1005
|
The source function's execution role must allow the operation that writes to the destination:
|
|
1020
1006
|
|
|
@@ -1154,11 +1140,9 @@ a config of its own, and an invocation of a qualifier with no config of its own
|
|
|
1154
1140
|
|
|
1155
1141
|
### Dead-letter targets
|
|
1156
1142
|
|
|
1157
|
-
`DeadLetterConfig`
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
record around it. The execution role needs `sqs:SendMessage` for a queue or `sns:Publish` for a
|
|
1161
|
-
topic. A denied delivery rejects the background task and leaves the target unchanged.
|
|
1143
|
+
`DeadLetterConfig` sends a failed asynchronous event to SQS or SNS. Configure it with
|
|
1144
|
+
`CreateFunction` or `UpdateFunctionConfiguration`. The target receives the original event rather
|
|
1145
|
+
than a destination record. The execution role needs `sqs:SendMessage` or `sns:Publish`.
|
|
1162
1146
|
|
|
1163
1147
|
```typescript sim-lambda-dead-letter-queue
|
|
1164
1148
|
/**
|
|
@@ -1249,11 +1233,9 @@ A function carrying both a dead-letter target and an `OnFailure` destination sen
|
|
|
1249
1233
|
|
|
1250
1234
|
## Versions and aliases
|
|
1251
1235
|
|
|
1252
|
-
`PublishVersionCommand`
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
`UpdateAliasCommand` moves the name to another version, so a deployment can repoint what callers
|
|
1256
|
-
invoke.
|
|
1236
|
+
`PublishVersionCommand` creates an immutable numbered copy of the function's code and configuration.
|
|
1237
|
+
Versions start at `1`. `CreateAliasCommand` gives a version a name, and `UpdateAliasCommand` moves
|
|
1238
|
+
that name to another version.
|
|
1257
1239
|
|
|
1258
1240
|
`InvokeCommand` and `GetFunctionCommand` take a `Qualifier` naming a version number or an alias.
|
|
1259
1241
|
The same qualifier can travel on the `FunctionName` instead, appended to the name (`orders:live`)
|
|
@@ -1366,9 +1348,8 @@ ARN. A `FunctionName` carrying a qualifier (`orders:live`) is refused with an
|
|
|
1366
1348
|
|
|
1367
1349
|
## Triggering a function from an SQS queue
|
|
1368
1350
|
|
|
1369
|
-
An event source mapping
|
|
1370
|
-
|
|
1371
|
-
real Lambda uses.
|
|
1351
|
+
An event source mapping polls a [simulated queue](https://yulinsim.dev/services/sqs/ "Simulated SQS docs") and invokes the function
|
|
1352
|
+
with an SQS `Records` event.
|
|
1372
1353
|
|
|
1373
1354
|
Polling runs on the simulation's background scheduler. A test awaits
|
|
1374
1355
|
`simAws.backgroundTasksComplete()` and then asserts, without sleeping.
|
|
@@ -1600,10 +1581,9 @@ from.
|
|
|
1600
1581
|
|
|
1601
1582
|
### When the handler fails
|
|
1602
1583
|
|
|
1603
|
-
A handler
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
what brings them back:
|
|
1584
|
+
A successful handler deletes the batch from the queue. When the handler throws, every message stays
|
|
1585
|
+
in flight until its visibility timeout expires, then becomes available for another delivery. Advance
|
|
1586
|
+
the simulated clock to reach that retry:
|
|
1607
1587
|
|
|
1608
1588
|
```typescript
|
|
1609
1589
|
await simAws.clock().advanceBy({ seconds: 31 });
|
|
@@ -1618,10 +1598,8 @@ the sender sees is the message coming back.
|
|
|
1618
1598
|
|
|
1619
1599
|
### Reporting individual message failures
|
|
1620
1600
|
|
|
1621
|
-
A queue mapping
|
|
1622
|
-
`batchItemFailures
|
|
1623
|
-
the rest of the batch is deleted. A stream mapping takes the same list and does something else with
|
|
1624
|
-
it, under [reporting individual record failures](#reporting-individual-record-failures).
|
|
1601
|
+
A queue mapping with `FunctionResponseTypes: ["ReportBatchItemFailures"]` reads the handler's
|
|
1602
|
+
`batchItemFailures`. Named message IDs return to the queue and the remaining messages are deleted.
|
|
1625
1603
|
|
|
1626
1604
|
```typescript
|
|
1627
1605
|
await simAws.lambda().createEventSourceMapping(
|
|
@@ -1646,9 +1624,8 @@ or an empty `batchItemFailures` list, has handled the whole batch.
|
|
|
1646
1624
|
|
|
1647
1625
|
### Making an SQS event without a queue
|
|
1648
1626
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
test then says what the messages carry and leaves the rest to the factory:
|
|
1627
|
+
Use `lambdaSqsEventFactory` and `lambdaSqsEventRecordFactory` to call an SQS handler without creating
|
|
1628
|
+
a queue or event source mapping:
|
|
1652
1629
|
|
|
1653
1630
|
```typescript sim-lambda-sqs-event-factory
|
|
1654
1631
|
/**
|
|
@@ -1702,11 +1679,15 @@ Reporting individual failures can be tested against a made event too. The handle
|
|
|
1702
1679
|
a template naming one is refused. The same Resource deploys a
|
|
1703
1680
|
[stream mapping](#stream-mappings-in-templates), which has to have one.
|
|
1704
1681
|
|
|
1682
|
+
`Tags` is the one property recorded rather than refused. A template's tags are usually the whole
|
|
1683
|
+
stack's (a CDK app calling `Tags.of(app).add(...)` tags every mapping in it), and a mapping delivers
|
|
1684
|
+
the same records whether it carries them or not. The deploy stands and nothing reads them back.
|
|
1685
|
+
|
|
1705
1686
|
## Triggering a function from a DynamoDB stream
|
|
1706
1687
|
|
|
1707
|
-
An event source mapping also
|
|
1708
|
-
|
|
1709
|
-
the `Records`
|
|
1688
|
+
An event source mapping can also poll a
|
|
1689
|
+
[simulated DynamoDB stream](https://yulinsim.dev/services/dynamodb/#capturing-changes-with-a-stream "Simulated DynamoDB streams docs").
|
|
1690
|
+
Table changes reach the handler as a DynamoDB `Records` event.
|
|
1710
1691
|
|
|
1711
1692
|
`StartingPosition` is required for a stream and is `TRIM_HORIZON` or `LATEST`. `TRIM_HORIZON` reads
|
|
1712
1693
|
what the stream still holds, so changes made before the mapping existed are delivered too. `LATEST`
|
|
@@ -2054,9 +2035,8 @@ because a message the handler never takes is left to the queue's own redrive pol
|
|
|
2054
2035
|
|
|
2055
2036
|
### Reporting individual record failures
|
|
2056
2037
|
|
|
2057
|
-
A stream mapping
|
|
2058
|
-
`batchItemFailures
|
|
2059
|
-
`SequenceNumber`:
|
|
2038
|
+
A stream mapping with `FunctionResponseTypes: ["ReportBatchItemFailures"]` reads the handler's
|
|
2039
|
+
`batchItemFailures`. Each item identifies a record by `SequenceNumber`:
|
|
2060
2040
|
|
|
2061
2041
|
```typescript
|
|
2062
2042
|
await simAws.lambda().createEventSourceMapping(
|
|
@@ -2304,15 +2284,13 @@ Write the grant as an inline policy, as the example above and CDK both do.
|
|
|
2304
2284
|
|
|
2305
2285
|
## Triggering a function from a Kinesis stream
|
|
2306
2286
|
|
|
2307
|
-
An event source mapping
|
|
2308
|
-
|
|
2309
|
-
`Records`
|
|
2287
|
+
An event source mapping can poll a
|
|
2288
|
+
[simulated Kinesis stream](https://yulinsim.dev/services/kinesis/ "Simulated Kinesis Data Streams docs") and invoke the function
|
|
2289
|
+
with a Kinesis `Records` event.
|
|
2310
2290
|
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
records from one shard, so a handler that has to see records in order should put them under one
|
|
2315
|
-
partition key, which is what puts them on one shard.
|
|
2291
|
+
Yulin reads every shard in a Kinesis stream. Each shard tracks its own iterator, delivers its own
|
|
2292
|
+
batches and backs off independently after a failure. An invocation receives records from one shard.
|
|
2293
|
+
Use one partition key when the handler requires ordered records.
|
|
2316
2294
|
|
|
2317
2295
|
`StartingPosition` is required for a stream. A Kinesis stream takes all three positions.
|
|
2318
2296
|
`TRIM_HORIZON` reads what the stream still holds, `LATEST` reads only what arrives from the moment
|
|
@@ -4268,7 +4246,9 @@ Current documented limitations:
|
|
|
4268
4246
|
- SQS queues, DynamoDB streams and Kinesis streams are the only event sources. Kafka, DocumentDB and
|
|
4269
4247
|
Kinesis enhanced fan-out consumers are refused outright, and so are `FilterCriteria`,
|
|
4270
4248
|
`ScalingConfig`, `DestinationConfig`, `BisectBatchOnFunctionError`, `ParallelizationFactor`,
|
|
4271
|
-
`TumblingWindowInSeconds` and the other mapping inputs this simulation has no behaviour for.
|
|
4249
|
+
`TumblingWindowInSeconds` and the other mapping inputs this simulation has no behaviour for. An
|
|
4250
|
+
`AWS::Lambda::EventSourceMapping` carrying `Tags` is the exception, and deploys with the tags
|
|
4251
|
+
dropped and the property recorded.
|
|
4272
4252
|
- A failed stream batch waits 1, 2, 4, 8 and 16 seconds between attempts, where AWS documents no
|
|
4273
4253
|
delay. That is deliberate. A delay of zero falls due at the instant the clock already reads, and a
|
|
4274
4254
|
handler that always throws would leave `advanceBy` with work falling due forever. A mapping that
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
# Simulated CloudWatch Logs
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
account.
|
|
7
|
-
|
|
8
|
-
The point of it is to make log data addressable. Code that writes to CloudWatch Logs is code teams
|
|
9
|
-
already have, and the alternative for a test is capturing process output.
|
|
3
|
+
Yulin simulates CloudWatch Logs in memory. It stores log groups, streams, and events. Application
|
|
4
|
+
code can write events through the normal SDK commands, and tests can read one stream with
|
|
5
|
+
`GetLogEvents` or search a group with `FilterLogEvents`.
|
|
10
6
|
|
|
11
7
|
CloudWatch Logs specific types are imported from the `@kensio/yulin/logs` subpath.
|
|
12
8
|
|
|
13
9
|
## Writing and searching log events
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
which execution environment wrote the line.
|
|
11
|
+
`FilterLogEvents` searches every stream in a group. A test can find an event without knowing which
|
|
12
|
+
execution environment wrote it.
|
|
18
13
|
|
|
19
14
|
```typescript sim-logs-write-and-search
|
|
20
15
|
/**
|
|
@@ -86,11 +81,9 @@ set of alternatives, and a quoted phrase matches with its spaces intact.
|
|
|
86
81
|
|
|
87
82
|
An omitted or empty pattern matches everything.
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
Yulin refuses structured pattern syntaxes. A JSON property pattern (`{ $.level = "ERROR" }`), a
|
|
90
85
|
space delimited field pattern (`[level=ERROR, message]`) and a regular expression term
|
|
91
|
-
(`%ERROR|WARN%`) each raise `SimLogsUnsupportedOperationException`.
|
|
92
|
-
worse. A pattern quietly treated as matching everything would turn an assertion about one log line
|
|
93
|
-
into an assertion about any log line at all, and the test would keep passing while testing nothing.
|
|
86
|
+
(`%ERROR|WARN%`) each raise `SimLogsUnsupportedOperationException`.
|
|
94
87
|
|
|
95
88
|
## Reading one stream
|
|
96
89
|
|
|
@@ -166,10 +159,8 @@ console.log(read);
|
|
|
166
159
|
|
|
167
160
|
## Retention
|
|
168
161
|
|
|
169
|
-
Retention is
|
|
170
|
-
|
|
171
|
-
ahead of the deletion that eventually follows from it. A log group with no retention keeps its
|
|
172
|
-
events forever, the AWS default.
|
|
162
|
+
Retention is stored and reported but leaves events in place. A log group without a retention setting
|
|
163
|
+
keeps events forever, matching the AWS default.
|
|
173
164
|
|
|
174
165
|
The accepted values are a fixed set. A reasonable-looking `retentionInDays: 10` is refused here
|
|
175
166
|
exactly as it is by an account.
|
|
@@ -210,9 +201,8 @@ console.log(
|
|
|
210
201
|
|
|
211
202
|
## Lambda handler output
|
|
212
203
|
|
|
213
|
-
A Lambda function
|
|
214
|
-
|
|
215
|
-
by searching its log group.
|
|
204
|
+
A simulated Lambda function writes its output to `/aws/lambda/<function name>`, whether it runs from
|
|
205
|
+
a zip archive or an in-process handler. Search that group to assert on handler output.
|
|
216
206
|
|
|
217
207
|
```typescript sim-logs-lambda-output
|
|
218
208
|
/**
|
|
@@ -256,11 +246,9 @@ const found = await simAws.logs().filterLogEvents(
|
|
|
256
246
|
console.log(found.events?.[0]?.message);
|
|
257
247
|
```
|
|
258
248
|
|
|
259
|
-
|
|
260
|
-
else, but a test tool that swallowed it would make a failing test harder to debug. Recording is a
|
|
261
|
-
tee.
|
|
249
|
+
Output also remains visible in the terminal to help diagnose failing tests.
|
|
262
250
|
|
|
263
|
-
An invocation that ends in an error
|
|
251
|
+
An invocation that ends in an uncaught error leaves an `ERROR Invoke Error` line in the group
|
|
264
252
|
after whatever it printed, carrying the error's type, its message and its stack. The
|
|
265
253
|
[simulated Lambda docs](https://yulinsim.dev/services/lambda/ "Simulated Lambda usage docs") show
|
|
266
254
|
one.
|
|
@@ -272,8 +260,8 @@ shape in a test, and leave the value alone.
|
|
|
272
260
|
|
|
273
261
|
Writing on this path is unconditional. A real function needs `logs:CreateLogGroup` and
|
|
274
262
|
`logs:PutLogEvents` on its execution Role, and one without them produces no logs at all, in silence.
|
|
275
|
-
|
|
276
|
-
|
|
263
|
+
Yulin always captures this output so missing log permissions do not hide diagnostic messages in
|
|
264
|
+
tests.
|
|
277
265
|
|
|
278
266
|
## Declaring a log group in a template
|
|
279
267
|
|
|
@@ -308,12 +296,11 @@ Two divergences to know about:
|
|
|
308
296
|
|
|
309
297
|
## Delivering logs from another service
|
|
310
298
|
|
|
311
|
-
CloudWatch Logs delivery
|
|
312
|
-
v2
|
|
313
|
-
means three CloudWatch Logs resources.
|
|
299
|
+
CloudWatch Logs delivery connects a service's log source to a destination. CloudFront standard
|
|
300
|
+
logging v2 uses a delivery source, a delivery destination, and a delivery.
|
|
314
301
|
|
|
315
|
-
|
|
316
|
-
|
|
302
|
+
The source identifies the resource and log type. The destination identifies where logs would go and
|
|
303
|
+
their output format. The delivery joins them.
|
|
317
304
|
|
|
318
305
|
```typescript sim-logs-delivery
|
|
319
306
|
/**
|
|
@@ -418,7 +405,7 @@ rules from real AWS are modelled here, each of them a deploy that looks fine unt
|
|
|
418
405
|
- **A delivery holds both its ends.** Deleting the source or the destination while a delivery joins
|
|
419
406
|
them fails with `ConflictException`. The delivery goes first, and CloudFormation orders that
|
|
420
407
|
itself when a stack is deleted.
|
|
421
|
-
- **CloudFront
|
|
408
|
+
- **CloudFront supports only `ACCESS_LOGS`.** Any other `logType` over a distribution is
|
|
422
409
|
refused.
|
|
423
410
|
- **CloudFront delivery is set up from `us-east-1`**, whatever region the destination bucket is in.
|
|
424
411
|
A CloudFront delivery source put from anywhere else is refused.
|
|
@@ -441,10 +428,9 @@ bare variables and let delivery name them.
|
|
|
441
428
|
|
|
442
429
|
### Declaring delivery in a template
|
|
443
430
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
deploy (see [the rules above](#delivering-logs-from-another-service)).
|
|
431
|
+
A CloudFormation template can declare the same three resources alongside the CloudFront distribution.
|
|
432
|
+
The source's `ResourceArn` can use `Ref` to include the generated distribution ID. A hard-coded ID
|
|
433
|
+
for a missing distribution fails deployment (see [the rules above](#delivering-logs-from-another-service)).
|
|
448
434
|
|
|
449
435
|
```yaml
|
|
450
436
|
SiteDistribution:
|
|
@@ -501,9 +487,9 @@ The template carries the S3 layout as two flat properties, and the API takes the
|
|
|
501
487
|
delivery. CloudWatch Logs issues that ID. A template cannot predict it.
|
|
502
488
|
|
|
503
489
|
`Fn::GetAtt` gives `Arn` on all three. The source also publishes `Service` and `ResourceArns`, and
|
|
504
|
-
the delivery publishes `DeliveryId` and `DeliveryDestinationType`. The destination publishes
|
|
505
|
-
|
|
506
|
-
|
|
490
|
+
the delivery publishes `DeliveryId` and `DeliveryDestinationType`. The destination publishes only
|
|
491
|
+
`Arn`. Read `DeliveryDestinationType` from the delivery rather than the destination. CloudFormation
|
|
492
|
+
refuses attributes outside this set.
|
|
507
493
|
|
|
508
494
|
`Tags` and `DeliveryDestinationPolicy` are recorded as ignored properties, and the stack still
|
|
509
495
|
deploys.
|
|
@@ -732,7 +718,8 @@ function is. `UpdateAlias` moves what the filter reaches, and the filter stays a
|
|
|
732
718
|
|
|
733
719
|
## Metric filters
|
|
734
720
|
|
|
735
|
-
A metric filter
|
|
721
|
+
A metric filter converts matching log events into CloudWatch metric datapoints. An alarm can then
|
|
722
|
+
watch the metric without application code calling `PutMetricData`.
|
|
736
723
|
|
|
737
724
|
```typescript sim-logs-metric-filter
|
|
738
725
|
/**
|
|
@@ -916,7 +903,9 @@ console.log(MetricAlarms?.[0]?.StateValue);
|
|
|
916
903
|
|
|
917
904
|
## Embedded Metric Format
|
|
918
905
|
|
|
919
|
-
A log event
|
|
906
|
+
A log event containing an Embedded Metric Format (EMF) document publishes its declared metrics.
|
|
907
|
+
AWS Lambda Powertools uses this path. It writes EMF to standard output instead of calling the
|
|
908
|
+
CloudWatch API.
|
|
920
909
|
|
|
921
910
|
```typescript sim-logs-embedded-metric-format
|
|
922
911
|
/**
|
|
@@ -997,7 +986,9 @@ A log event is read as a document only where it parses as JSON, comes out as an
|
|
|
997
986
|
|
|
998
987
|
Three things go on `simAws.logs().metricPublicationFailures` rather than passing quietly. A metric the metadata declares and the document body carries no number under, a metric asking for `StorageResolution: 1`, which simulated CloudWatch has no period short enough for, and a directive that asked for dimensions and got no usable set of them.
|
|
999
988
|
|
|
1000
|
-
A dimension set is
|
|
989
|
+
A dimension set is accepted or dropped as a whole. Yulin drops a set when the body lacks one of its
|
|
990
|
+
keys or a value has a type other than string. Publishing only part of the set would create the wrong
|
|
991
|
+
metric identity. A directive without a usable set produces no datapoint.
|
|
1001
992
|
|
|
1002
993
|
Each entry on the ledger names its `source`, which is `{ kind: "metricFilter", filterName }` or `{ kind: "embeddedMetricFormat" }`. The two are told apart by kind rather than by name, because a metric filter may be called anything.
|
|
1003
994
|
|
|
@@ -1132,7 +1123,7 @@ console.log(described.logGroups?.[0]?.logGroupArn);
|
|
|
1132
1123
|
- **Events never expire.** Retention is stored and reported, never acted on.
|
|
1133
1124
|
- **A metric filter reading a field of the log event.** A `metricValue` or a dimension value
|
|
1134
1125
|
beginning `$` is refused where the filter is put. Both need a structured filter pattern, and
|
|
1135
|
-
|
|
1126
|
+
both require a structured syntax, which Yulin refuses.
|
|
1136
1127
|
- **How far back a `defaultValue` looks.** A filter remembers the most recent minute it matched
|
|
1137
1128
|
something in. A later write into that same minute publishes no default over the top, and a write
|
|
1138
1129
|
landing in an earlier minute a match was already seen in does publish one. Events
|
|
@@ -1143,21 +1134,21 @@ console.log(described.logGroups?.[0]?.logGroupArn);
|
|
|
1143
1134
|
read, which is how it reaches CloudWatch in an account.
|
|
1144
1135
|
- **`AWS::Logs::SubscriptionFilter`.** Recorded as a gap. The log group, the metric filter and the
|
|
1145
1136
|
three delivery resource types are what simulated CloudFormation deploys here.
|
|
1146
|
-
- **`ApplyOnTransformedLogs` and `EmitSystemFieldDimensions` on a metric filter.** Recorded
|
|
1147
|
-
|
|
1148
|
-
- **
|
|
1137
|
+
- **`ApplyOnTransformedLogs` and `EmitSystemFieldDimensions` on a metric filter.** Recorded as
|
|
1138
|
+
ignored properties. Log transformers are absent.
|
|
1139
|
+
- **Delivery resources store configuration only.** A delivery records that a source was joined to a destination
|
|
1149
1140
|
and how the records would be written. No access log file ever reaches the bucket.
|
|
1150
1141
|
- **`GetDeliverySource`, `GetDeliveryDestination` and `GetDelivery`.** Absent as SDK operations. The
|
|
1151
1142
|
three `Describe` operations report the same resources. The three action names are authorized where
|
|
1152
1143
|
CloudFormation reads a delivery Resource back.
|
|
1153
1144
|
- **Delivery resource tags and cross-account delivery.** `PutDeliverySource`,
|
|
1154
1145
|
`PutDeliveryDestination` and `CreateDelivery` refuse tags outright. `DeliveryDestinationPolicy` in
|
|
1155
|
-
a template is recorded
|
|
1146
|
+
a template is recorded as an ignored property.
|
|
1156
1147
|
- **An `=` in a suffix path with Hive compatible paths off.** Taken. Whether real CloudWatch Logs
|
|
1157
1148
|
takes one is unverified. A path hand-rolling its own partition keys without the option is left
|
|
1158
1149
|
alone here, and refused with the option on.
|
|
1159
|
-
- **Log types for services other than CloudFront.**
|
|
1160
|
-
|
|
1150
|
+
- **Log types for services other than CloudFront.** Yulin accepts any `logType` for resources other
|
|
1151
|
+
than distributions because the valid set varies by service.
|
|
1161
1152
|
- **Logs Insights, export tasks, tags, encryption and data protection policies.** Absent. Tags and
|
|
1162
1153
|
`kmsKeyId` on `CreateLogGroup` are refused outright. A property cannot look set here and behave
|
|
1163
1154
|
differently in an account.
|