@kensio/yulin 1.21.15 → 1.21.17

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.
Files changed (58) hide show
  1. package/dist/sdk/router/sim-sdk-command-router.type.d.ts +9 -0
  2. package/dist/sdk/sim-sdk-command-dispatcher.js +1 -1
  3. package/dist/service/cloudformation/changeset/sim-cfn-change-set-changes.js +1 -1
  4. package/dist/service/cloudformation/resource/factory/sim-cfn-resource-factory.type.d.ts +25 -1
  5. package/dist/service/cloudformation/resource/resolve/service/sim-cfn-resource-service-factory.d.ts +18 -0
  6. package/dist/service/cloudformation/resource/resolve/service/sim-cfn-resource-service-factory.js +30 -0
  7. package/dist/service/cloudformation/resource/sim-cfn-resource.type.d.ts +18 -0
  8. package/dist/service/cloudformation/resource/update/sim-cfn-resource-in-place-updater.d.ts +35 -0
  9. package/dist/service/cloudformation/resource/update/sim-cfn-resource-in-place-updater.js +61 -0
  10. package/dist/service/cloudformation/resource/update/sim-cfn-resource-update-error.d.ts +9 -0
  11. package/dist/service/cloudformation/resource/update/sim-cfn-resource-update-error.js +14 -0
  12. package/dist/service/cloudformation/resource/update/sim-cfn-resource-update-validator.js +5 -18
  13. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +7 -2
  14. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +16 -12
  15. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-change-pairs.d.ts +12 -0
  16. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-change-pairs.js +18 -0
  17. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-changes.d.ts +52 -0
  18. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-changes.js +86 -0
  19. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-updates.d.ts +42 -0
  20. package/dist/service/cloudformation/stack/update/sim-cfn-stack-resource-updates.js +70 -0
  21. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.d.ts +25 -18
  22. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.js +43 -32
  23. package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.d.ts +7 -5
  24. package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js +12 -7
  25. package/dist/service/dynamodb/document/sim-dynamodb-document-marshall-options.d.ts +42 -0
  26. package/dist/service/dynamodb/document/sim-dynamodb-document-marshall-options.js +36 -0
  27. package/dist/service/dynamodb/document/sim-dynamodb-document-marshall.d.ts +6 -5
  28. package/dist/service/dynamodb/document/sim-dynamodb-document-marshall.js +37 -43
  29. package/dist/service/dynamodb/document/sim-dynamodb-document-number.d.ts +4 -2
  30. package/dist/service/dynamodb/document/sim-dynamodb-document-number.js +5 -3
  31. package/dist/service/dynamodb/document/sim-dynamodb-document-path.d.ts +0 -4
  32. package/dist/service/dynamodb/document/sim-dynamodb-document-path.js +17 -10
  33. package/dist/service/dynamodb/document/sim-dynamodb-document-route.js +5 -1
  34. package/dist/service/dynamodb/document/sim-dynamodb-document-scalar.d.ts +13 -0
  35. package/dist/service/dynamodb/document/sim-dynamodb-document-scalar.js +46 -0
  36. package/dist/service/dynamodb/document/sim-dynamodb-document-set.d.ts +8 -3
  37. package/dist/service/dynamodb/document/sim-dynamodb-document-set.js +21 -14
  38. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-change.d.ts +19 -0
  39. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-change.js +39 -0
  40. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-deleter.d.ts +23 -0
  41. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-deleter.js +23 -0
  42. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-template.test-support.d.ts +21 -0
  43. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-template.test-support.js +64 -0
  44. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-update.test-support.d.ts +18 -0
  45. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-update.test-support.js +39 -0
  46. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-updater.d.ts +37 -0
  47. package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-updater.js +66 -0
  48. package/dist/service/secretsmanager/cfn/sim-cfn-secrets-manager-resource-factory.d.ts +20 -10
  49. package/dist/service/secretsmanager/cfn/sim-cfn-secrets-manager-resource-factory.js +41 -27
  50. package/dist/service/secretsmanager/cfn/sim-cfn-secrets-manager-resource-type.d.ts +12 -0
  51. package/dist/service/secretsmanager/cfn/sim-cfn-secrets-manager-resource-type.js +22 -0
  52. package/docs/sdk/README.md +5 -4
  53. package/docs/services/cloudformation/README.md +21 -3
  54. package/docs/services/dynamodb/README.md +81 -2
  55. package/docs/services/secretsmanager/README.md +35 -1
  56. package/package.json +1 -1
  57. package/dist/service/cloudformation/stack/update/sim-cfn-stack-replaced-resources.d.ts +0 -21
  58. package/dist/service/cloudformation/stack/update/sim-cfn-stack-replaced-resources.js +0 -51
@@ -1,51 +1,65 @@
1
1
  import { simCfnResourceCallerOptions } from "../../cloudformation/resource/caller/sim-cfn-resource-caller-options.js";
2
2
  import { SimCfnSecretsManagerSecretCreator } from "./secret/sim-cfn-secrets-manager-secret-creator.js";
3
- import { assertDefined } from "../../../util/type-guard/defined.js";
3
+ import { SimCfnSecretsManagerSecretDeleter } from "./secret/sim-cfn-secrets-manager-secret-deleter.js";
4
+ import { SimCfnSecretsManagerSecretUpdater } from "./secret/sim-cfn-secrets-manager-secret-updater.js";
5
+ import { simCfnSecretsManagerSecretReplaced } from "./secret/sim-cfn-secrets-manager-secret-change.js";
6
+ import { isSimCfnSecretsManagerSecret, requireSimCfnSecretsManagerSecret, } from "./sim-cfn-secrets-manager-resource-type.js";
4
7
  /**
5
8
  * CloudFormation Resource factory for simulated Secrets Manager resources.
9
+ *
10
+ * Only `Secret` is deployed. Rotation, resource policies and target
11
+ * attachments are not simulated, so their Resource types are reported as
12
+ * unsupported and skipped rather than quietly treated as deployed.
6
13
  */
7
14
  export class SimSecretsManagerCfnResourceFactory {
8
- secretsManager;
9
15
  secretCreator;
16
+ secretUpdater;
17
+ secretDeleter;
10
18
  constructor(properties) {
11
- this.secretsManager = properties.secretsManager;
19
+ const { secretsManager } = properties;
12
20
  this.secretCreator = new SimCfnSecretsManagerSecretCreator({
13
- secretsManager: properties.secretsManager,
21
+ secretsManager,
22
+ });
23
+ this.secretUpdater = new SimCfnSecretsManagerSecretUpdater({
24
+ secretsManager,
25
+ });
26
+ this.secretDeleter = new SimCfnSecretsManagerSecretDeleter({
27
+ secretsManager,
14
28
  });
15
29
  }
16
30
  /**
17
31
  * Create a simulated Secrets Manager resource from a CloudFormation
18
32
  * Resource.
19
- *
20
- * Rotation, resource policies and target attachments are not simulated, so
21
- * their Resource types are reported as unsupported and skipped rather than
22
- * quietly treated as deployed.
23
33
  */
24
34
  async create(resourceTypeName, resource, context) {
25
- switch (resourceTypeName) {
26
- case "Secret": {
27
- return await this.secretCreator.create(resource, context.resolvedProperties ?? resource.properties, simCfnResourceCallerOptions(context.caller));
28
- }
29
- default: {
30
- throw new Error(`Unsupported sim Secrets Manager CloudFormation Resource ${resourceTypeName}`);
31
- }
32
- }
35
+ requireSimCfnSecretsManagerSecret(resourceTypeName);
36
+ return await this.secretCreator.create(resource, context.resolvedProperties ?? resource.properties, simCfnResourceCallerOptions(context.caller));
37
+ }
38
+ /**
39
+ * Whether a changed secret can be applied to the deployed one.
40
+ *
41
+ * Name is the only property real CloudFormation replaces a secret for.
42
+ * Everything else is applied with no interruption, which is what keeps a
43
+ * generated value across a change to the secret's description or tags.
44
+ */
45
+ updatesInPlace(resourceTypeName, current, updated) {
46
+ return (isSimCfnSecretsManagerSecret(resourceTypeName) &&
47
+ !simCfnSecretsManagerSecretReplaced(current, updated));
48
+ }
49
+ /**
50
+ * Apply a changed AWS::SecretsManager::Secret Resource to the deployed
51
+ * secret.
52
+ */
53
+ async updateInPlace(resourceTypeName, current, updated, context) {
54
+ requireSimCfnSecretsManagerSecret(resourceTypeName, "update");
55
+ return await this.secretUpdater.update(current, updated, context);
33
56
  }
34
57
  /**
35
58
  * Delete a simulated Secrets Manager resource created from a CloudFormation
36
59
  * Resource.
37
- *
38
- * DeleteSecret schedules the deletion rather than carrying it out, so a torn
39
- * down Stack leaves a secret waiting out its recovery window. That is what
40
- * CloudFormation does: the secret is recoverable afterwards, which is the
41
- * point of the window.
42
60
  */
43
61
  async delete(resourceTypeName, resource, context) {
44
- if (resourceTypeName !== "Secret") {
45
- throw new Error(`Unsupported sim Secrets Manager CloudFormation Resource ${resourceTypeName} deletion`);
46
- }
47
- const secret = resource.simResource;
48
- assertDefined(secret, `sim Secrets Manager secret for CloudFormation Resource ${resource.logicalId}`);
49
- await this.secretsManager.deleteSecret({ input: { SecretId: secret.arn.value } }, simCfnResourceCallerOptions(context.caller));
62
+ requireSimCfnSecretsManagerSecret(resourceTypeName, "deletion");
63
+ await this.secretDeleter.delete(resource, simCfnResourceCallerOptions(context.caller));
50
64
  }
51
65
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether a Resource type name is the secret this simulation deploys.
3
+ */
4
+ export declare function isSimCfnSecretsManagerSecret(resourceTypeName: string): boolean;
5
+ /**
6
+ * Refuse an operation on a Resource type this simulation does not deploy.
7
+ *
8
+ * The refusal reads as an unsupported Resource, so the Stack records it and
9
+ * carries on rather than failing. Creation names no operation, since a
10
+ * Resource type nothing creates is the plain case a reader meets first.
11
+ */
12
+ export declare function requireSimCfnSecretsManagerSecret(resourceTypeName: string, operation?: string): void;
@@ -0,0 +1,22 @@
1
+ /** The one AWS::SecretsManager::* Resource type this simulation deploys. */
2
+ const secretResourceTypeName = "Secret";
3
+ /**
4
+ * Whether a Resource type name is the secret this simulation deploys.
5
+ */
6
+ export function isSimCfnSecretsManagerSecret(resourceTypeName) {
7
+ return resourceTypeName === secretResourceTypeName;
8
+ }
9
+ /**
10
+ * Refuse an operation on a Resource type this simulation does not deploy.
11
+ *
12
+ * The refusal reads as an unsupported Resource, so the Stack records it and
13
+ * carries on rather than failing. Creation names no operation, since a
14
+ * Resource type nothing creates is the plain case a reader meets first.
15
+ */
16
+ export function requireSimCfnSecretsManagerSecret(resourceTypeName, operation) {
17
+ if (isSimCfnSecretsManagerSecret(resourceTypeName)) {
18
+ return;
19
+ }
20
+ const refused = operation === undefined ? "" : ` ${operation}`;
21
+ throw new Error(`Unsupported sim Secrets Manager CloudFormation Resource ${resourceTypeName}${refused}`);
22
+ }
@@ -282,7 +282,8 @@ service throws `SimSdkUnknownServiceError`.
282
282
  - Simulated errors have SDK-shaped `name` and `$metadata` fields. They are separate classes from the
283
283
  SDK exceptions, so match them by `error.name` instead of `instanceof`.
284
284
  - The callback form of `send(command, callback)` is not supported. Use the promise form.
285
- - Yulin ignores the translation options in
286
- `DynamoDBDocumentClient.from(client, { marshallOptions, unmarshallOptions })`. The conversion uses
287
- the defaults. `removeUndefinedValues: true` has no effect. Yulin refuses an `undefined` attribute
288
- that the configured document client would otherwise remove.
285
+ - Yulin reads the `marshallOptions` in
286
+ `DynamoDBDocumentClient.from(client, { marshallOptions, unmarshallOptions })` and ignores the
287
+ `unmarshallOptions`. A stored value comes back the way a document client built with no options of
288
+ its own reads it. See
289
+ [the DynamoDB docs](https://yulinsim.dev/services/dynamodb/#marshalling-options).
@@ -446,6 +446,22 @@ Replacement also affects dependencies and retention policies:
446
446
  The deployed one was deleted to make room for the replacement, and there is nothing left to put
447
447
  back. See [rolling back a failed update](#rolling-back-a-failed-update) below.
448
448
 
449
+ ### Resources a service changes where they are
450
+
451
+ A service can claim a change for the properties real CloudFormation applies with no interruption.
452
+ The resource is then left where it is. It keeps its physical name and everything it holds, and
453
+ every resource naming it is left standing too.
454
+
455
+ `AWS::SecretsManager::Secret` is the one resource type that does this so far. `Name` is the only
456
+ property real CloudFormation replaces a secret for. A change to anything else is applied to the
457
+ deployed secret, which keeps its ARN and its versions across the update. See the
458
+ [simulated Secrets Manager docs](https://yulinsim.dev/services/secretsmanager/ "Simulated Secrets Manager usage docs")
459
+ for which changes write a new secret version and which leave the value alone.
460
+
461
+ These changes are applied first, while everything the stack had is still deployed. An update that
462
+ fails on one has deleted nothing yet. A claimed resource the replacement spread reaches is replaced
463
+ after all, and the claim is taken back, since its dependency is being deleted and created again.
464
+
449
465
  ### Rolling back a failed update
450
466
 
451
467
  A failed update is rolled back onto the template the stack was deployed from. The stack moves to
@@ -4393,13 +4409,15 @@ Each service's own docs describe what its resource types support.
4393
4409
  [properties a Resource was created without](#properties-a-resource-was-created-without) for what
4394
4410
  is still refused outright.
4395
4411
  - A stack update replaces a changed resource rather than updating it in place, so what the resource
4396
- held is lost. See [changed resources are replaced](#changed-resources-are-replaced).
4412
+ held is lost. `AWS::SecretsManager::Secret` is the exception. See
4413
+ [changed resources are replaced](#changed-resources-are-replaced) and
4414
+ [resources a service changes where they are](#resources-a-service-changes-where-they-are).
4397
4415
  - A watched template file updates its stack in place. That makes the update itself no gentler. A
4398
4416
  changed resource is still replaced and loses what it holds, the same as any other update.
4399
4417
  - Yulin never synthesizes a CDK app. It watches the synthesized output template. A change to the app
4400
4418
  itself reaches the stack once something has run `cdk synth` over it.
4401
- - A change set reports every `Modify` as `Replacement: True`, because a changed resource is replaced
4402
- rather than updated in place. `ChangeSetType: IMPORT` is refused, and so is a `CREATE` change set
4419
+ - A change set reports every `Modify` as `Replacement: True`, even for a resource an update would
4420
+ change where it is. `ChangeSetType: IMPORT` is refused, and so is a `CREATE` change set
4403
4421
  naming a stack that is already there, where CloudFormation allows a second one against a stack
4404
4422
  still in review. Drift detection is outside the simulation.
4405
4423
  - A rolled-back update recreates a resource it had already replaced, and the resource comes back
@@ -3040,6 +3040,84 @@ Intercept the document client itself. `DynamoDBDocumentClient.from(client)` buil
3040
3040
  outside the `DynamoDBClient` class, so intercepting the base client leaves Commands sent through the
3041
3041
  document one untouched. See [the SDK docs](https://yulinsim.dev/sdk/#the-dynamodb-document-client).
3042
3042
 
3043
+ ### Marshalling options
3044
+
3045
+ `DynamoDBDocumentClient.from(client, { marshallOptions })` changes what the conversion does with a
3046
+ value the defaults refuse. Yulin reads those options off the client each Command was sent through.
3047
+ Two document clients over one simulation each convert by their own.
3048
+
3049
+ - `removeUndefinedValues` drops an `undefined` out of a map, a list or a `Set`. Without it, an
3050
+ `undefined` in any of the three is refused. The real client refuses it in the same place.
3051
+ - `convertEmptyValues` writes an empty string, an empty binary value and an empty `Set` as `NULL`.
3052
+ - `convertClassInstanceToMap` reads an object with behaviour as a map of its own properties.
3053
+ - `allowImpreciseNumbers` writes a number past `Number.MAX_SAFE_INTEGER` with the digits it has
3054
+ already been rounded to.
3055
+
3056
+ An `undefined` attribute of an item, a key or a set of expression values is left out whatever the
3057
+ client was built with. `removeUndefinedValues` governs the values held inside an attribute, and the
3058
+ attributes of an item sit a level above that (the real client drops an undefined one there without
3059
+ being asked to).
3060
+
3061
+ ```typescript sim-dynamodb-document-marshall-options
3062
+ /**
3063
+ * Writing a partly filled object through a document client that drops
3064
+ * undefined values.
3065
+ */
3066
+
3067
+ import { CreateTableCommand, DynamoDBClient } from "@aws-sdk/client-dynamodb";
3068
+ import {
3069
+ DynamoDBDocumentClient,
3070
+ GetCommand,
3071
+ PutCommand,
3072
+ } from "@aws-sdk/lib-dynamodb";
3073
+
3074
+ import { SimSdk } from "@kensio/yulin/sdk";
3075
+
3076
+ using simSdk = new SimSdk();
3077
+
3078
+ const documents = DynamoDBDocumentClient.from(
3079
+ new DynamoDBClient({ region: "eu-west-2" }),
3080
+ { marshallOptions: { removeUndefinedValues: true } },
3081
+ );
3082
+ simSdk.intercept(documents);
3083
+
3084
+ await documents.send(
3085
+ new CreateTableCommand({
3086
+ TableName: "PagesTable",
3087
+ KeySchema: [{ AttributeName: "pageId", KeyType: "HASH" }],
3088
+ AttributeDefinitions: [{ AttributeName: "pageId", AttributeType: "S" }],
3089
+ BillingMode: "PAY_PER_REQUEST",
3090
+ }),
3091
+ );
3092
+ await simSdk.simAws.backgroundTasksComplete();
3093
+
3094
+ // The summary was never filled in, and one section is still to be written.
3095
+ await documents.send(
3096
+ new PutCommand({
3097
+ TableName: "PagesTable",
3098
+ Item: {
3099
+ pageId: "page-1",
3100
+ meta: { title: "Home", summary: undefined },
3101
+ sections: ["intro", undefined, "outro"],
3102
+ },
3103
+ }),
3104
+ );
3105
+
3106
+ const read = await documents.send(
3107
+ new GetCommand({ TableName: "PagesTable", Key: { pageId: "page-1" } }),
3108
+ );
3109
+
3110
+ const meta = read.Item?.["meta"] as Record<string, string>;
3111
+ console.log(Object.keys(meta)); // [ 'title' ]
3112
+
3113
+ // A dropped member takes its position with it.
3114
+ const sections = read.Item?.["sections"] as string[];
3115
+ console.log(sections); // [ 'intro', 'outro' ]
3116
+ ```
3117
+
3118
+ `unmarshallOptions` are ignored. A stored value comes back the way a document client built with no
3119
+ options of its own reads it.
3120
+
3043
3121
  ### Querying and scanning through the document client
3044
3122
 
3045
3123
  `@aws-sdk/lib-dynamodb` names its `QueryCommand` and `ScanCommand` exactly as
@@ -3152,8 +3230,9 @@ A simulated table holds a number's digits exactly, but the document client conve
3152
3230
  JavaScript numbers, and that is where digits are lost. It is the same loss AWS has. A test that
3153
3231
  passes here is telling you something true about the real thing.
3154
3232
 
3155
- - Writing a `number` outside the safe integer range is refused, never stored already rounded. Write
3156
- a `bigint`, or a `NumberValue` from `@aws-sdk/lib-dynamodb`, to keep the digits.
3233
+ - Writing a `number` outside the safe integer range is refused unless the client was built with
3234
+ `allowImpreciseNumbers`. Write a `bigint`, or a `NumberValue` from `@aws-sdk/lib-dynamodb`, to keep
3235
+ the digits.
3157
3236
  - Reading a stored number outside the safe integer range gives a `bigint`.
3158
3237
  - Reading a stored decimal with more digits than a JavaScript number carries gives a rounded
3159
3238
  `number`. The table still holds every digit, and the rounding is the document client's. Read
@@ -428,6 +428,37 @@ console.log(credentials.password?.length); // 24
428
428
  Generated passwords are random. Read the deployed value through Secrets Manager instead of asserting
429
429
  on an exact password.
430
430
 
431
+ ## Updating a deployed secret
432
+
433
+ `Name` is the only property real CloudFormation replaces a secret for. A stack update that changes
434
+ anything else applies it to the deployed secret, which keeps its ARN and its versions.
435
+
436
+ A change to the description, the tags or the KMS key leaves the value alone. That is what carries a
437
+ generated password across an update, and it keeps a resource that read the secret as the stack
438
+ deployed, such as a CloudFront origin custom header, holding the value the secret still has.
439
+
440
+ A new version is written when the template asks for a different value, which is a changed
441
+ `SecretString` or a changed `GenerateSecretString`. A changed `GenerateSecretString` generates a new
442
+ password, as real CloudFormation writes a new version for one. **A resource that resolved the old
443
+ value keeps it.** Its own template entry is unchanged, so the update leaves it alone, and it goes on
444
+ holding what it read at deploy time. A consumer that has to follow the value must read the secret
445
+ when it runs, the way a Lambda function given the secret's ARN does, rather than take a copy through
446
+ a `{{resolve:secretsmanager:...}}` reference.
447
+
448
+ The template is the desired state. A property the new template leaves out is cleared. A dropped
449
+ `Description` is emptied, and a dropped `KmsKeyId` puts the secret back on the `aws/secretsmanager`
450
+ key. Versions already written keep the key they were made with and stay
451
+ readable.
452
+
453
+ Changing the `Name` replaces the secret. The new one is created under the new name and the old one
454
+ is scheduled for deletion, waiting out its recovery window.
455
+
456
+ A secret is also replaced when a resource it names is replaced, because the update deletes and
457
+ recreates that resource and the secret would otherwise be applied against the one on its way out.
458
+ That replacement then fails, since the name is held for the recovery window. Real CloudFormation
459
+ updates the secret in place and hands it the new physical name. Nothing is applied to the deployed
460
+ secret before the failure.
461
+
431
462
  ## Reading a secret with a dynamic reference
432
463
 
433
464
  A `{{resolve:secretsmanager:...}}` dynamic reference reads an existing secret while CloudFormation
@@ -641,7 +672,10 @@ code into the simulation, served in process. See
641
672
  empty page.
642
673
  - Tags are stored and reported by `DescribeSecret` and `ListSecrets`, but `TagResource` and
643
674
  `UntagResource` are absent, and the `secretsmanager:ResourceTag` and `aws:ResourceTag` condition
644
- keys are left underived.
675
+ keys are left underived. A stack update applies the tags its template declares to the deployed
676
+ secret, since there is no command to ask for it with.
677
+ - A stack update authorizes the whole change as `secretsmanager:UpdateSecret`. Real CloudFormation
678
+ needs `secretsmanager:TagResource` as well for a change to the tags.
645
679
  - Other Secrets Manager condition keys, such as `secretsmanager:SecretId` and
646
680
  `secretsmanager:VersionStage`, are left underived too, and a policy relying on them fails to match.
647
681
  Ordinary condition operators on values sim IAM does supply work as usual.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kensio/yulin",
3
- "version": "1.21.15",
3
+ "version": "1.21.17",
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/",
@@ -1,21 +0,0 @@
1
- import type { SimCfnResource } from "../../resource/sim-cfn-resource.js";
2
- interface SimCfnStackReplacedResourcesProperties {
3
- readonly current: ReadonlyMap<string, SimCfnResource>;
4
- readonly updated: ReadonlyMap<string, SimCfnResource>;
5
- }
6
- /**
7
- * The logical IDs an update has to replace, given the Stack's deployed
8
- * Resources and the ones its new template describes.
9
- *
10
- * A Resource is replaced when its resolved template entry changed. Sim
11
- * CloudFormation has no in-place update, so replacement means deleting the
12
- * Resource and creating it again from the new template.
13
- *
14
- * A Resource that names a replaced Resource is replaced too, all the way up the
15
- * dependency chain. Real CloudFormation hands the dependent the new physical
16
- * name instead, but nothing here can rewrite an already created simulated
17
- * Resource, and leaving the dependent alone would leave it pointing at a
18
- * Resource that has gone.
19
- */
20
- export declare function simCfnStackReplacedLogicalIds(properties: SimCfnStackReplacedResourcesProperties): ReadonlySet<string>;
21
- export {};
@@ -1,51 +0,0 @@
1
- import { simCfnTemplateSignature } from "./sim-cfn-template-signature.js";
2
- /**
3
- * The logical IDs an update has to replace, given the Stack's deployed
4
- * Resources and the ones its new template describes.
5
- *
6
- * A Resource is replaced when its resolved template entry changed. Sim
7
- * CloudFormation has no in-place update, so replacement means deleting the
8
- * Resource and creating it again from the new template.
9
- *
10
- * A Resource that names a replaced Resource is replaced too, all the way up the
11
- * dependency chain. Real CloudFormation hands the dependent the new physical
12
- * name instead, but nothing here can rewrite an already created simulated
13
- * Resource, and leaving the dependent alone would leave it pointing at a
14
- * Resource that has gone.
15
- */
16
- export function simCfnStackReplacedLogicalIds(properties) {
17
- const { current, updated } = properties;
18
- const replaced = changedLogicalIds({ current, updated });
19
- // Each pass replaces the Resources naming one already being replaced, until a
20
- // pass finds none, which is the end of the dependency chain.
21
- let spreading = true;
22
- while (spreading) {
23
- spreading = false;
24
- for (const [logicalId, resource] of updated) {
25
- const spreads = current.has(logicalId) &&
26
- !replaced.has(logicalId) &&
27
- resource.dependencies().some((dependency) => replaced.has(dependency));
28
- if (spreads) {
29
- replaced.add(logicalId);
30
- spreading = true;
31
- }
32
- }
33
- }
34
- return replaced;
35
- }
36
- /**
37
- * The logical IDs whose resolved template entry differs from the deployed one.
38
- */
39
- function changedLogicalIds(properties) {
40
- const { current, updated } = properties;
41
- const changed = new Set();
42
- for (const [logicalId, resource] of updated) {
43
- const deployed = current.get(logicalId);
44
- if (deployed !== undefined &&
45
- simCfnTemplateSignature(deployed.template) !==
46
- simCfnTemplateSignature(resource.template)) {
47
- changed.add(logicalId);
48
- }
49
- }
50
- return changed;
51
- }