@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,18 +1,12 @@
|
|
|
1
1
|
# Simulated CloudFront
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
3
|
+
Yulin simulates CloudFront distributions, origins, cache behaviour and edge functions. Use
|
|
4
|
+
`simAws.cloudFront()` as part of a simulated AWS environment or create a standalone
|
|
5
|
+
`SimCloudFront`. `serveSimAws` exposes distributions over localhost.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
alongside other simulated AWS services, so application code can make HTTP requests through a
|
|
7
|
-
CloudFront-like layer without talking to real AWS.
|
|
7
|
+
## Create a distribution
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
standing apart from any wider simulated AWS environment.
|
|
11
|
-
|
|
12
|
-
## Basic Distribution setup
|
|
13
|
-
|
|
14
|
-
Create a simulated AWS environment, add a sim S3 Bucket, and create a sim CloudFront Distribution
|
|
15
|
-
pointing at that Bucket.
|
|
9
|
+
Create an S3 bucket, then create a distribution whose origin uses the bucket's REST endpoint.
|
|
16
10
|
|
|
17
11
|
```typescript sim-cloudfront-distribution-s3-origin
|
|
18
12
|
/**
|
|
@@ -95,19 +89,16 @@ console.log(distributionCreation.Distribution?.DomainName);
|
|
|
95
89
|
|
|
96
90
|
## What an S3 Origin can read
|
|
97
91
|
|
|
98
|
-
An S3 Origin reads its
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Distribution to serve it, and a Bucket with no policy answers 403 for every Object.
|
|
92
|
+
An S3 Origin reads its bucket through `GetObject`. The bucket policy decides what the distribution
|
|
93
|
+
can serve. Without an origin access control, CloudFront reads anonymously and the object must be
|
|
94
|
+
publicly readable. A private bucket returns 403.
|
|
102
95
|
|
|
103
96
|
An Origin that does have an origin access control reads as the CloudFront service principal. The
|
|
104
97
|
Bucket stays private and its policy names the Distribution. See
|
|
105
98
|
[Origin access controls](#origin-access-controls) for the Bucket policy that takes.
|
|
106
99
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
`Principal: "*"`. The same pair is what a static website Bucket needs, and it is what CDK's
|
|
110
|
-
`publicReadAccess: true` generates.
|
|
100
|
+
The example disables the block on public bucket policies, then grants `s3:GetObject` to
|
|
101
|
+
`Principal: "*"`. CDK's `publicReadAccess: true` produces the same result.
|
|
111
102
|
|
|
112
103
|
A denied read reaches the viewer as a 403 from the Origin, and a Distribution's custom error
|
|
113
104
|
response for 403 replaces it. The usual single-page-app setup, rewriting 403 to `/index.html`,
|
|
@@ -118,10 +109,8 @@ an Origin that signs nothing.
|
|
|
118
109
|
|
|
119
110
|
## Static sites, default root objects and error pages
|
|
120
111
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
matches no object return the site's own error page in place of the Origin's. Sim CloudFront applies
|
|
124
|
-
both, and a test can assert what a visitor would actually see.
|
|
112
|
+
`DefaultRootObject` maps the distribution root to an object such as `index.html`.
|
|
113
|
+
`CustomErrorResponses` replaces selected Origin errors with another object and status code.
|
|
125
114
|
|
|
126
115
|
```typescript sim-cloudfront-static-site
|
|
127
116
|
/**
|
|
@@ -242,13 +231,10 @@ try {
|
|
|
242
231
|
}
|
|
243
232
|
```
|
|
244
233
|
|
|
245
|
-
The default root object
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
CloudFront Function both act on the object being served. The value names an object at the Origin. It may be a
|
|
250
|
-
path such as `public/index.html`, and it must not begin with a forward slash. Sim CloudFront refuses one that does with `InvalidDefaultRootObject`. The alternative would
|
|
251
|
-
be a Distribution that answers its own root with a 403.
|
|
234
|
+
The default root object applies only to `/`. A request for `/blog/` reaches the Origin unchanged,
|
|
235
|
+
even if the Origin contains `/blog/index.html`. Cache Behaviors and viewer-request functions see the
|
|
236
|
+
substituted root path. The value may contain a path such as `public/index.html`, but it must not start
|
|
237
|
+
with `/`. Invalid values raise `InvalidDefaultRootObject`.
|
|
252
238
|
|
|
253
239
|
A custom error response replaces the Origin's response when its status matches `ErrorCode`. The
|
|
254
240
|
codes CloudFront supports are 400, 403, 404, 405, 414, 416, 500, 501, 502, 503 and 504. The response
|
|
@@ -276,7 +262,7 @@ status the Distribution serves no page for. See
|
|
|
276
262
|
|
|
277
263
|
## Serve simulated CloudFront on localhost
|
|
278
264
|
|
|
279
|
-
Use `serveSimAws`
|
|
265
|
+
Use `serveSimAws` to send HTTP requests through the simulated distribution on localhost.
|
|
280
266
|
|
|
281
267
|
```typescript serve-sim-cloudfront-localhost
|
|
282
268
|
/**
|
|
@@ -390,15 +376,14 @@ the Distribution behind it. See
|
|
|
390
376
|
|
|
391
377
|
## Custom Origins
|
|
392
378
|
|
|
393
|
-
An Origin with
|
|
394
|
-
|
|
395
|
-
|
|
379
|
+
An Origin with `CustomOriginConfig` routes requests to another simulated HTTP service. CloudFront
|
|
380
|
+
resolves `DomainName` in the simulated environment and serves the request in process. A distribution
|
|
381
|
+
can front a simulated HTTP API endpoint
|
|
396
382
|
(`<api-id>.execute-api.<region>.amazonaws.com`), a simulated Lambda Function URL
|
|
397
383
|
(`<url-id>.lambda-url.<region>.on.aws`), or anything a simulated Route53 record points at one of
|
|
398
384
|
those.
|
|
399
385
|
|
|
400
|
-
|
|
401
|
-
sending `/api/*` to an API:
|
|
386
|
+
The following distribution serves static files from S3 and sends `/api/*` to an HTTP API:
|
|
402
387
|
|
|
403
388
|
```typescript sim-cloudfront-distribution-custom-origin
|
|
404
389
|
/**
|
|
@@ -568,14 +553,13 @@ try {
|
|
|
568
553
|
}
|
|
569
554
|
```
|
|
570
555
|
|
|
571
|
-
The Origin domain is resolved
|
|
572
|
-
|
|
573
|
-
declare them.
|
|
556
|
+
The Origin domain is resolved for each request. The distribution and Origin service may be created
|
|
557
|
+
in either order.
|
|
574
558
|
|
|
575
559
|
`OriginPath` is prefixed to the request path, as it is for an S3 Origin. An Origin path of `/v1`
|
|
576
560
|
sends a request for `/things` on to `/v1/things`.
|
|
577
561
|
|
|
578
|
-
|
|
562
|
+
In-process routing has these limits:
|
|
579
563
|
|
|
580
564
|
- A domain unknown to the simulation fails with an error naming the Origin and the
|
|
581
565
|
domain. No real request is made to it, and external HTTP Origins are unsupported.
|
|
@@ -588,10 +572,9 @@ Three things follow from the request never leaving the process:
|
|
|
588
572
|
|
|
589
573
|
## Custom headers on an Origin
|
|
590
574
|
|
|
591
|
-
CloudFront adds an Origin's custom headers to every request
|
|
592
|
-
|
|
593
|
-
[
|
|
594
|
-
and a sim Distribution sends them the same way.
|
|
575
|
+
CloudFront adds an Origin's custom headers to every request sent to that Origin. A service can use a
|
|
576
|
+
private header value to
|
|
577
|
+
[restrict access to CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-overview.html#forward-custom-headers-restrict-access).
|
|
595
578
|
|
|
596
579
|
The CloudFront API and CloudFormation name the field differently, and both spellings are accepted
|
|
597
580
|
here. The API has `CustomHeaders` inside an `Origin`, and `AWS::CloudFront::Distribution` has
|
|
@@ -741,10 +724,10 @@ An S3 Origin takes the headers and reaches nothing with them. Sim CloudFront rea
|
|
|
741
724
|
`GetObject` and builds no HTTP request for a header to travel on, and real S3 ignores a header it
|
|
742
725
|
has no use for.
|
|
743
726
|
|
|
744
|
-
##
|
|
727
|
+
## Duplicate Origins
|
|
745
728
|
|
|
746
|
-
|
|
747
|
-
|
|
729
|
+
Several Origins may use the same domain when their paths, headers, or connection settings differ.
|
|
730
|
+
Each Behavior selects an Origin by ID.
|
|
748
731
|
|
|
749
732
|
Two Origins that match in every property but the `Id` are one Origin written twice. Copying a
|
|
750
733
|
Behavior and its Origin together, then editing the path pattern, leaves exactly that behind. Sim
|
|
@@ -840,9 +823,8 @@ value however they were ordered or cased.
|
|
|
840
823
|
|
|
841
824
|
## Viewer certificates
|
|
842
825
|
|
|
843
|
-
A
|
|
844
|
-
|
|
845
|
-
reject at deploy time is rejected here first, with `InvalidViewerCertificate`:
|
|
826
|
+
A distribution with alternate domain names requires a valid ACM certificate. Yulin raises
|
|
827
|
+
`InvalidViewerCertificate` when:
|
|
846
828
|
|
|
847
829
|
- the certificate must be in `us-east-1`, wherever the rest of your infrastructure lives
|
|
848
830
|
- the certificate must exist and be `ISSUED`
|
|
@@ -912,8 +894,8 @@ as well.
|
|
|
912
894
|
|
|
913
895
|
## Disabling and deleting a Distribution
|
|
914
896
|
|
|
915
|
-
|
|
916
|
-
|
|
897
|
+
Disable a distribution with `UpdateDistributionCommand` before deleting it. Deleting an enabled
|
|
898
|
+
distribution raises `DistributionNotDisabled`.
|
|
917
899
|
|
|
918
900
|
`UpdateDistributionCommand` takes a whole `DistributionConfig`, and applies the update as a
|
|
919
901
|
replacement. Anything left out of the new config is dropped, including alternate domain names and
|
|
@@ -1012,17 +994,16 @@ Function code.
|
|
|
1012
994
|
|
|
1013
995
|
## Simulated CloudFront Functions
|
|
1014
996
|
|
|
1015
|
-
|
|
997
|
+
Yulin supports `viewer-request` and `viewer-response` CloudFront Functions.
|
|
1016
998
|
|
|
1017
999
|
A `viewer-response` Function runs for an Origin status below 400. CloudFront skips the
|
|
1018
1000
|
viewer-response event once the Origin has answered 400 or higher (see
|
|
1019
1001
|
[Limitations](#limitations)), and so does this simulation.
|
|
1020
1002
|
|
|
1021
|
-
Use `makeCffFunctionCodeInput` to pass a JavaScript handler
|
|
1003
|
+
Use `makeCffFunctionCodeInput` to pass a JavaScript handler to `CreateFunctionCommand`. Use
|
|
1022
1004
|
[CloudFormation bindings](https://yulinsim.dev/services/cloudformation/#cloudfront-function-bindings "CloudFront Function bindings usage docs")
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
about the code the Distribution carries, down to the 10 KB it has to fit in. A
|
|
1005
|
+
for a function declared in a template. Handler references support breakpoints and local state. Use
|
|
1006
|
+
source code when the test covers the deployed function or its 10 KB size limit. A
|
|
1026
1007
|
[Lambda@Edge](#simulated-lambdaedge) function is an ordinary simulated Lambda function, and the same
|
|
1027
1008
|
choice covers it.
|
|
1028
1009
|
|
|
@@ -1851,8 +1832,7 @@ parameter holding the version ARN into a support stack in us-east-1. The stack u
|
|
|
1851
1832
|
reads that parameter back through a `Custom::CrossRegionStringParameterReader` resource, and the
|
|
1852
1833
|
Behavior's `LambdaFunctionARN` is an `Fn::GetAtt` on it. Simulated CloudFormation makes that read
|
|
1853
1834
|
itself, against the Region the resource names, and the association ends up holding the ARN the
|
|
1854
|
-
support stack published.
|
|
1855
|
-
assembly does:
|
|
1835
|
+
support stack published. Deploy the whole cloud assembly to deploy both stacks:
|
|
1856
1836
|
|
|
1857
1837
|
```typescript
|
|
1858
1838
|
await simAws.cloudFormation().deployCdkOut("cdk.out");
|
|
@@ -2014,8 +1994,8 @@ answered.
|
|
|
2014
1994
|
## Response headers policies
|
|
2015
1995
|
|
|
2016
1996
|
A response headers policy sets headers on everything a cache Behavior serves. Declare one as
|
|
2017
|
-
`AWS::CloudFront::ResponseHeadersPolicy` and
|
|
2018
|
-
|
|
1997
|
+
`AWS::CloudFront::ResponseHeadersPolicy` and reference it from the Behavior's
|
|
1998
|
+
`ResponseHeadersPolicyId`. CDK's `ResponseHeadersPolicy` construct synthesizes this shape.
|
|
2019
1999
|
|
|
2020
2000
|
```typescript sim-cloudfront-response-headers-policy
|
|
2021
2001
|
/**
|
|
@@ -2206,9 +2186,9 @@ it.
|
|
|
2206
2186
|
|
|
2207
2187
|
## Cache policies
|
|
2208
2188
|
|
|
2209
|
-
A cache policy
|
|
2210
|
-
|
|
2211
|
-
`
|
|
2189
|
+
A cache policy controls the cache key and time to live. Declare one as
|
|
2190
|
+
`AWS::CloudFront::CachePolicy` and reference it from the Behavior's `CachePolicyId`. CDK's
|
|
2191
|
+
`CachePolicy` construct synthesizes this shape.
|
|
2212
2192
|
|
|
2213
2193
|
```typescript sim-cloudfront-cache-policy
|
|
2214
2194
|
/**
|
|
@@ -2652,8 +2632,8 @@ try {
|
|
|
2652
2632
|
|
|
2653
2633
|
The Origin's own headers and the cache policy settle the TTL between them, the way they settle it in
|
|
2654
2634
|
AWS. `s-maxage` is preferred to `max-age`, and `max-age` to `Expires`. Whatever the Origin asks for
|
|
2655
|
-
is held between the policy's `MinTTL` and `MaxTTL`.
|
|
2656
|
-
of `MinTTL` and `DefaultTTL
|
|
2635
|
+
is held between the policy's `MinTTL` and `MaxTTL`. When the Origin supplies no cache lifetime,
|
|
2636
|
+
CloudFront uses the greater of `MinTTL` and `DefaultTTL`. `CachingOptimized` uses one day.
|
|
2657
2637
|
|
|
2658
2638
|
An `Expires` header has to carry one of the three date formats HTTP allows. Anything else, a
|
|
2659
2639
|
locale-formatted date included, is read as an object that expired already, the way any HTTP cache
|
|
@@ -2878,10 +2858,9 @@ different paths is `InvalidationBatchAlreadyExists`.
|
|
|
2878
2858
|
|
|
2879
2859
|
## Origin request policies
|
|
2880
2860
|
|
|
2881
|
-
An origin request policy
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
construct synthesizes.
|
|
2861
|
+
An origin request policy selects the viewer headers, cookies and query strings sent to the Origin.
|
|
2862
|
+
Declare one as `AWS::CloudFront::OriginRequestPolicy` and reference it from the Behavior's
|
|
2863
|
+
`OriginRequestPolicyId`. CDK's `OriginRequestPolicy` construct synthesizes this shape.
|
|
2885
2864
|
|
|
2886
2865
|
```typescript sim-cloudfront-origin-request-policy
|
|
2887
2866
|
/**
|
|
@@ -3171,9 +3150,9 @@ Behavior names one without a template creating anything. `AllViewer`
|
|
|
3171
3150
|
for it. CDK's `OriginRequestPolicy.ALL_VIEWER` and its seven siblings synthesize those IDs. A stack
|
|
3172
3151
|
reaching for one deploys.
|
|
3173
3152
|
|
|
3174
|
-
Each also carries the three sections AWS publishes for it. A Behavior on `AllViewer`
|
|
3175
|
-
|
|
3176
|
-
|
|
3153
|
+
Each also carries the three sections AWS publishes for it. A Behavior on `AllViewer` sends every
|
|
3154
|
+
viewer value except `Host`. The Origin's domain is used for `Host` under every policy. A Behavior on
|
|
3155
|
+
`CORS-CustomOrigin` sends the `Origin` header alone. One on
|
|
3177
3156
|
`AllViewerExceptHostHeader` sends what `AllViewer` sends, since the `Host` it withholds was never
|
|
3178
3157
|
the viewer's here.
|
|
3179
3158
|
|
|
@@ -3189,10 +3168,9 @@ Behavior, the way an absent cache policy does, and the Behavior reports no polic
|
|
|
3189
3168
|
|
|
3190
3169
|
## Origin access controls
|
|
3191
3170
|
|
|
3192
|
-
An origin access control
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
`S3BucketOrigin.withOriginAccessControl` synthesizes.
|
|
3171
|
+
An origin access control lets a Distribution authenticate to a private Origin. Declare one as
|
|
3172
|
+
`AWS::CloudFront::OriginAccessControl` and reference it from the Origin's `OriginAccessControlId`.
|
|
3173
|
+
CDK's `S3BucketOrigin.withOriginAccessControl` synthesizes this shape.
|
|
3196
3174
|
|
|
3197
3175
|
An `OriginAccessControlOriginType` of `s3` signs for an S3 Bucket Origin, and one of `lambda` signs
|
|
3198
3176
|
for a Lambda Function URL Origin. The origin type has to match the Origin it is attached to. An `s3`
|
|
@@ -3635,11 +3613,9 @@ CloudFront. `await simAws.backgroundTasksComplete()` waits for that.
|
|
|
3635
3613
|
|
|
3636
3614
|
### ETags
|
|
3637
3615
|
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
and a caller has to thread the ETag through the way it does against CloudFront. Each write returns
|
|
3642
|
-
the new ETag for the next one.
|
|
3616
|
+
Key value store commands check `IfMatch`. Distribution and Function commands ignore it. Both key
|
|
3617
|
+
value store APIs require the current ETag for every write. A stale ETag raises
|
|
3618
|
+
`PreconditionFailed`, and each successful write returns the ETag for the next one.
|
|
3643
3619
|
|
|
3644
3620
|
A store has two ETags and they are not interchangeable, as in AWS. Each `DescribeKeyValueStore`
|
|
3645
3621
|
returns its own. The CloudFront client's versions the store's configuration, and the key value store
|
|
@@ -3993,8 +3969,8 @@ Where sim CloudFront knowingly behaves differently from AWS:
|
|
|
3993
3969
|
response an `origin-request` function generated has no Origin status behind it, and its own status
|
|
3994
3970
|
stands in.
|
|
3995
3971
|
- **CloudFront's disallowed and read-only header lists go unchecked.** Real CloudFront answers 502
|
|
3996
|
-
when an edge function adds `Connection` or edits `Content-Length`.
|
|
3997
|
-
|
|
3972
|
+
when an edge function adds `Connection` or edits `Content-Length`. Yulin accepts those changes.
|
|
3973
|
+
It restores the `host` after a viewer-request function.
|
|
3998
3974
|
- **An S3 Origin with no origin access control reads its Bucket anonymously.** That is the unsigned
|
|
3999
3975
|
request real CloudFront sends to the S3 REST endpoint without one. The Bucket policy has to make
|
|
4000
3976
|
an Object publicly readable for the Distribution to serve it. A legacy
|
|
@@ -4020,9 +3996,9 @@ Where sim CloudFront knowingly behaves differently from AWS:
|
|
|
4020
3996
|
are absent, and `AWS::CloudFront::OriginAccessControl` is the only way to make one.
|
|
4021
3997
|
- **A list's `Quantity` is only checked when it is there.** Every CloudFront list carries a count
|
|
4022
3998
|
alongside its items, and a `Quantity` that disagrees with `Items` is refused with
|
|
4023
|
-
`InconsistentQuantities`, as CloudFront refuses it.
|
|
4024
|
-
|
|
4025
|
-
|
|
3999
|
+
`InconsistentQuantities`, as CloudFront refuses it. CloudFormation uses a plain array without a
|
|
4000
|
+
count, so templates skip this validation. A hand-written `{ Items: [...] }` also skips it when the
|
|
4001
|
+
count is absent. The AWS SDK types make omitting
|
|
4026
4002
|
`Quantity` a compile error, so what arrives without one is a different mistake from the one this
|
|
4027
4003
|
catches.
|
|
4028
4004
|
- **A web ACL a Distribution names has to exist here.** `WebACLId` resolves to a web ACL created in
|
|
@@ -4075,11 +4051,9 @@ Where sim CloudFront knowingly behaves differently from AWS:
|
|
|
4075
4051
|
share of real responses carry `Server-Timing`. This simulation adds it to every response once
|
|
4076
4052
|
`Enabled` is true. A test asserting on it never depends on chance. The header's value is a
|
|
4077
4053
|
fixed placeholder, since nothing here measures an Origin fetch the way CloudFront's edge does.
|
|
4078
|
-
- **
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
-
|
|
4083
|
-
`
|
|
4084
|
-
forwards nothing. `Host`, `User-Agent` and the normalized `Accept-Encoding` are the three this
|
|
4085
|
-
simulation sends of its own accord.
|
|
4054
|
+
- **Origin requests use the Origin's `Host` header.** Real CloudFront can forward the viewer's value
|
|
4055
|
+
when a policy includes it. Yulin always sends the Origin domain because the request must reach the
|
|
4056
|
+
simulated service named by the URL.
|
|
4057
|
+
- **CloudFront-generated headers are absent.** Yulin omits `X-Amz-Cf-Id`, `Via`,
|
|
4058
|
+
`X-Forwarded-For` and the `CloudFront-Viewer-*` family. It generates `Host`, `User-Agent` and a
|
|
4059
|
+
normalized `Accept-Encoding` value.
|
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
# Simulated CloudWatch Metrics
|
|
2
2
|
|
|
3
|
-
Yulin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
it was to assert that the SDK client had been called. That proves the call was made. What it
|
|
10
|
-
measured goes untested.
|
|
11
|
-
|
|
12
|
-
Most of what lives here is custom metrics. Simulated Lambda publishes its own `AWS/Lambda`
|
|
13
|
-
`Invocations`, `Errors`, `Duration` and `IteratorAge`, simulated Cognito publishes a pool's
|
|
14
|
-
`AWS/Cognito` counts, and no other simulated service publishes into an `AWS/` namespace yet. A
|
|
15
|
-
query for one nothing measures comes back empty, in place of a number that was never taken. A test
|
|
16
|
-
can stand a datapoint up for one of those itself, which is what drives an alarm on a service metric
|
|
17
|
-
to a state change.
|
|
3
|
+
Yulin simulates CloudWatch metrics and alarms in memory. Application code can publish datapoints and
|
|
4
|
+
read their statistics through the normal CloudWatch commands. Alarms evaluate on simulated time and
|
|
5
|
+
can notify simulated SNS topics.
|
|
6
|
+
|
|
7
|
+
Simulated Lambda publishes `AWS/Lambda` metrics, and simulated Cognito publishes `AWS/Cognito`
|
|
8
|
+
metrics. Tests can seed other AWS-managed metrics through the service writer described below.
|
|
18
9
|
|
|
19
10
|
A custom metric's datapoints arrive either from `PutMetricData` or from a CloudWatch Logs metric
|
|
20
11
|
filter counting matching log events. See the [CloudWatch Logs docs](../logs/README.md) for the
|
|
@@ -24,8 +15,8 @@ CloudWatch specific types are imported from the `@kensio/yulin/cloudwatch` subpa
|
|
|
24
15
|
|
|
25
16
|
## Publishing and reading back a metric
|
|
26
17
|
|
|
27
|
-
A metric is identified by its namespace,
|
|
28
|
-
|
|
18
|
+
A metric is identified by its namespace, name, and exact set of dimensions. Publish a value and
|
|
19
|
+
read it back over a period:
|
|
29
20
|
|
|
30
21
|
```typescript sim-cloudwatch-publish-and-read
|
|
31
22
|
/**
|
|
@@ -84,18 +75,14 @@ the way out. A query naming a unit CloudWatch lacks fails here as it would in an
|
|
|
84
75
|
|
|
85
76
|
## Metrics are identified by their dimensions
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
That is the behaviour teams most often get wrong, and it is worth a test of its own. A dashboard
|
|
92
|
-
query written against a metric name alone finds nothing at all if every publish carried a dimension.
|
|
78
|
+
CloudWatch treats each exact set of dimensions as a separate metric. Publishing the same metric name
|
|
79
|
+
with two dimension values creates two metrics. A query without dimensions reads only datapoints
|
|
80
|
+
published without dimensions.
|
|
93
81
|
|
|
94
82
|
## Metrics and simulated time
|
|
95
83
|
|
|
96
|
-
A datum
|
|
97
|
-
|
|
98
|
-
datapoints in the period it moved to:
|
|
84
|
+
A datum without a `Timestamp` uses the simulation's clock. Set or advance the clock to place
|
|
85
|
+
datapoints in exact periods:
|
|
99
86
|
|
|
100
87
|
```typescript sim-cloudwatch-simulated-time
|
|
101
88
|
/**
|
|
@@ -153,11 +140,14 @@ window drops a metric out of the listing without anything having to expire it.
|
|
|
153
140
|
|
|
154
141
|
## Metrics a simulated service publishes
|
|
155
142
|
|
|
156
|
-
|
|
143
|
+
Callers publish custom metrics through `PutMetricData`. AWS-managed metrics use namespaces beginning
|
|
144
|
+
with `AWS/`, which callers cannot publish into.
|
|
157
145
|
|
|
158
|
-
|
|
146
|
+
Simulated Cognito publishes counts under `AWS/Cognito`, dimensioned by `UserPool` and
|
|
147
|
+
`UserPoolClient`. See the [Cognito docs](../cognito/README.md).
|
|
159
148
|
|
|
160
|
-
Simulated Lambda publishes
|
|
149
|
+
Simulated Lambda publishes `Invocations`, `Duration`, and `Errors` under `AWS/Lambda`, dimensioned by
|
|
150
|
+
`FunctionName`. These metrics require no extra configuration or execution-role permission.
|
|
161
151
|
|
|
162
152
|
```typescript sim-cloudwatch-lambda-errors
|
|
163
153
|
/**
|
|
@@ -217,13 +207,15 @@ const { MetricAlarms } = await simAws
|
|
|
217
207
|
console.log(MetricAlarms?.[0]?.StateValue);
|
|
218
208
|
```
|
|
219
209
|
|
|
220
|
-
`Duration`
|
|
210
|
+
`Duration` uses the simulation's clock rather than the host's. A handler that advances the clock
|
|
211
|
+
reports that elapsed time, while a handler that leaves it unchanged reports zero duration.
|
|
212
|
+
`IteratorAge` uses the same clock. The Lambda documentation describes the value reported by a stream
|
|
213
|
+
event source mapping.
|
|
221
214
|
|
|
222
215
|
## Seeding a metric AWS publishes
|
|
223
216
|
|
|
224
|
-
`PutMetricData` refuses
|
|
225
|
-
|
|
226
|
-
The service writer is the way in. It is the same route simulated Lambda's own metrics take, reached from a test through `cloudWatch().serviceWriter()`, and it stands a datapoint up in any namespace.
|
|
217
|
+
`PutMetricData` refuses namespaces beginning with `AWS/`. To test an alarm for another AWS-managed
|
|
218
|
+
metric, add the datapoint through `cloudWatch().serviceWriter()`.
|
|
227
219
|
|
|
228
220
|
```typescript sim-cloudwatch-seed-service-metric
|
|
229
221
|
/**
|
|
@@ -286,14 +278,13 @@ console.log(MetricAlarms?.[0]?.StateValue);
|
|
|
286
278
|
|
|
287
279
|
A datapoint arriving without a `timestamp` is stamped with the simulation's clock. One carrying its own lands where it says, which fills a window without the clock having to be walked through it.
|
|
288
280
|
|
|
289
|
-
|
|
281
|
+
The service writer is a test setup API. `PutMetricData` keeps its reserved-namespace validation.
|
|
290
282
|
|
|
291
283
|
## Alarms
|
|
292
284
|
|
|
293
|
-
An alarm watches one metric and changes state on the simulation's clock
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
line of the test runs.
|
|
285
|
+
An alarm watches one metric and changes state on the simulation's clock. Each evaluation is scheduled
|
|
286
|
+
at the next period boundary. Advancing time by twenty minutes runs twenty one-minute evaluations and
|
|
287
|
+
settles before the next line of the test.
|
|
297
288
|
|
|
298
289
|
```typescript sim-cloudwatch-alarm
|
|
299
290
|
/**
|
|
@@ -353,8 +344,8 @@ console.log(described.MetricAlarms?.at(0)?.StateValue);
|
|
|
353
344
|
```
|
|
354
345
|
|
|
355
346
|
A new alarm is in `INSUFFICIENT_DATA` until it has evaluated a period, as on real CloudWatch. The
|
|
356
|
-
window it looks back over reaches behind the moment the alarm was created. An alarm over
|
|
357
|
-
|
|
347
|
+
window it looks back over reaches behind the moment the alarm was created. An alarm over an empty
|
|
348
|
+
metric, with `TreatMissingData: "breaching"`, therefore fires on its first
|
|
358
349
|
evaluation, without waiting for the periods to accumulate. That is what an account does too.
|
|
359
350
|
|
|
360
351
|
### Reaching a subscriber
|
|
@@ -458,10 +449,9 @@ had never named them.
|
|
|
458
449
|
|
|
459
450
|
## Permissions
|
|
460
451
|
|
|
461
|
-
CloudWatch metrics have no ARN,
|
|
462
|
-
|
|
463
|
-
`arn:aws:cloudwatch:eu-west-2:111111111111:metric/Orders/Failed`
|
|
464
|
-
account.
|
|
452
|
+
CloudWatch metrics have no ARN, so every metric action uses a resource of `*`. A policy written
|
|
453
|
+
against a fabricated metric ARN such as
|
|
454
|
+
`arn:aws:cloudwatch:eu-west-2:111111111111:metric/Orders/Failed` is invalid in Yulin and AWS.
|
|
465
455
|
|
|
466
456
|
Alarms are the exception, and do have an ARN. `PutMetricAlarm`, `DeleteAlarms` and `SetAlarmState`
|
|
467
457
|
authorize against `arn:aws:cloudwatch:<region>:<account>:alarm:<name>`, while `DescribeAlarms` and
|
|
@@ -525,7 +515,7 @@ await simAws.cloudWatch().putMetricData(
|
|
|
525
515
|
// Publishing into any other namespace as this Role is denied.
|
|
526
516
|
```
|
|
527
517
|
|
|
528
|
-
##
|
|
518
|
+
## Supported operations
|
|
529
519
|
|
|
530
520
|
- `PutMetricData`, with `Value`, `StatisticValues` and `Values`/`Counts`.
|
|
531
521
|
- `ListMetrics`, filtered by namespace, metric name and dimensions, with `RecentlyActive` and
|
|
@@ -546,11 +536,9 @@ await simAws.cloudWatch().putMetricData(
|
|
|
546
536
|
- `AWS::CloudWatch::Alarm` in simulated CloudFormation, deployed through `PutMetricAlarm` and taken
|
|
547
537
|
down with the stack.
|
|
548
538
|
|
|
549
|
-
##
|
|
539
|
+
## Unsupported operations and options
|
|
550
540
|
|
|
551
|
-
|
|
552
|
-
rather than accepted and ignored. A silently dropped filter is worse than a failure, because the
|
|
553
|
-
test still passes and no longer means what it says.
|
|
541
|
+
Yulin rejects unsupported CloudWatch behavior instead of ignoring it:
|
|
554
542
|
|
|
555
543
|
- **Composite and anomaly detection alarms.** `Metrics` and `ThresholdMetricId` on `PutMetricAlarm`
|
|
556
544
|
are refused. There is no trained model here for an anomaly band to come from.
|
|
@@ -571,8 +559,6 @@ test still passes and no longer means what it says.
|
|
|
571
559
|
through the service writer. A CloudWatch Logs metric filter naming a reserved namespace is refused
|
|
572
560
|
when it publishes, as `PutMetricData` refuses a caller naming one.
|
|
573
561
|
|
|
574
|
-
Two
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
CloudWatch's contract permits without promising, because a test reading the third period of five
|
|
578
|
-
needs an order it can rely on.
|
|
562
|
+
Two behaviors differ from AWS. Yulin accepts datapoints more than two weeks old or more than two
|
|
563
|
+
hours in the future, which makes it easier to seed a test window. It also returns datapoints in
|
|
564
|
+
ascending timestamp order so tests receive deterministic results.
|