@kensio/yulin 1.20.15 → 1.20.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.
- package/README.md +13 -0
- package/dist/sdk/module/sim-sdk-module-client-interceptor.d.ts +5 -0
- package/dist/sdk/module/sim-sdk-module-client-interceptor.js +14 -0
- package/dist/sdk/module/sim-sdk-static-client-factory.d.ts +26 -0
- package/dist/sdk/module/sim-sdk-static-client-factory.js +59 -0
- package/dist/sdk/send-patch.d.ts +8 -0
- package/dist/sdk/send-patch.js +11 -0
- package/dist/service/aws/caller/sim-aws-ambient-caller.d.ts +23 -0
- package/dist/service/aws/caller/sim-aws-ambient-caller.js +12 -0
- package/dist/service/aws/caller/sim-aws-caller-resolver.d.ts +39 -6
- package/dist/service/aws/caller/sim-aws-caller-resolver.js +32 -30
- package/dist/service/aws/caller/sim-aws-caller.d.ts +9 -0
- package/dist/service/aws/caller/sim-aws-resolved-caller.d.ts +19 -0
- package/dist/service/aws/caller/sim-aws-resolved-caller.js +26 -0
- package/dist/service/aws/factory/sim-aws-account-region-service-builder.d.ts +12 -0
- package/dist/service/aws/factory/sim-aws-account-region-service-builder.js +6 -0
- package/dist/service/aws/factory/sim-aws-account-service-cache.d.ts +12 -0
- package/dist/service/aws/factory/sim-aws-account-service-cache.js +9 -0
- package/dist/service/aws/factory/sim-aws-registered-service-builder.js +3 -1
- package/dist/service/aws/factory/sim-aws-service-factory.d.ts +5 -0
- package/dist/service/aws/factory/sim-aws-service-factory.js +14 -0
- package/dist/service/aws/sim-aws-properties.d.ts +15 -0
- package/dist/service/aws/sim-aws.js +2 -1
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.d.ts +4 -0
- package/dist/service/cloudformation/command/create-stack/create-stack.handler.js +4 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-deployer.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.d.ts +11 -2
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-plan.js +2 -1
- package/dist/service/cloudformation/deploy/sim-cfn-cdk-out-stack-options.d.ts +6 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +11 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +17 -15
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +12 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +2 -1
- package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cache-policy-cfn.d.ts +23 -0
- package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cache-policy-cfn.js +30 -0
- package/dist/service/cloudformation/resource/cfn/cloudfront/sim-cloudfront-cfn-value-adapter.js +8 -0
- package/dist/service/cloudformation/resource/name/sim-cfn-generated-resource-name.d.ts +29 -12
- package/dist/service/cloudformation/resource/name/sim-cfn-generated-resource-name.js +51 -20
- package/dist/service/cloudformation/stack/deploy/sim-cfn-resource-order.d.ts +19 -0
- package/dist/service/cloudformation/stack/deploy/sim-cfn-resource-order.js +6 -0
- package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-batch-creator.d.ts +7 -0
- package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-batch-creator.js +9 -2
- package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-creator.d.ts +2 -0
- package/dist/service/cloudformation/stack/deploy/sim-cfn-stack-resource-creator.js +2 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +6 -0
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +4 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.js +2 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.type.d.ts +6 -0
- package/dist/service/cloudfront/behaviour/sim-cloud-front-behavior.d.ts +5 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy-registry.d.ts +37 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy-registry.js +50 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy.d.ts +25 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-cache-policy.js +21 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-managed-cache-policies.d.ts +28 -0
- package/dist/service/cloudfront/cache-policy/sim-cf-managed-cache-policies.js +48 -0
- package/dist/service/cloudfront/cff/function-code-input/cff-function-code-input.d.ts +8 -0
- package/dist/service/cloudfront/cff/function-code-input/cff-function-code-input.js +13 -0
- package/dist/service/cloudfront/cff/sim-cf-function-commands.d.ts +52 -0
- package/dist/service/cloudfront/cff/sim-cf-function-commands.js +51 -0
- package/dist/service/cloudfront/cff/sim-cff-configuration.d.ts +41 -0
- package/dist/service/cloudfront/cff/sim-cff-configuration.js +34 -0
- package/dist/service/cloudfront/cff/sim-cff-stage.d.ts +23 -0
- package/dist/service/cloudfront/cff/sim-cff-stage.js +30 -0
- package/dist/service/cloudfront/cff/sim-cloudfront-function.d.ts +6 -1
- package/dist/service/cloudfront/cff/sim-cloudfront-function.js +6 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-config.d.ts +27 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-config.js +42 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.d.ts +24 -0
- package/dist/service/cloudfront/cfn/cache-policy/sim-cfn-cf-cache-policy-creator.js +32 -0
- package/dist/service/cloudfront/cfn/distro/{sim-cfn-cf-distro-response-headers-policy.d.ts → sim-cfn-cf-distro-behavior-policies.d.ts} +8 -7
- package/dist/service/cloudfront/cfn/distro/{sim-cfn-cf-distro-response-headers-policy.js → sim-cfn-cf-distro-behavior-policies.js} +11 -37
- package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-creator.d.ts +6 -5
- package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-creator.js +8 -7
- package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-policy-drops.d.ts +23 -0
- package/dist/service/cloudfront/cfn/distro/sim-cfn-cf-distro-policy-drops.js +50 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.d.ts +1 -0
- package/dist/service/cloudfront/cfn/sim-cfn-cloudfront-resource-factory.js +10 -0
- package/dist/service/cloudfront/command/create-distribution/create-distribution.command.d.ts +1 -0
- package/dist/service/cloudfront/command/create-distribution/create-distribution.handler.d.ts +2 -0
- package/dist/service/cloudfront/command/create-function/create-function.handler.js +7 -1
- package/dist/service/cloudfront/command/function/sim-cf-describe-function.d.ts +22 -0
- package/dist/service/cloudfront/command/function/sim-cf-describe-function.js +32 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-access.d.ts +48 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-access.js +48 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-command.types.d.ts +97 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-command.types.js +10 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-lookup.d.ts +12 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-lookup.js +21 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-summary.d.ts +11 -0
- package/dist/service/cloudfront/command/function/sim-cf-function-summary.js +30 -0
- package/dist/service/cloudfront/command/function/sim-cf-get-function.d.ts +23 -0
- package/dist/service/cloudfront/command/function/sim-cf-get-function.js +33 -0
- package/dist/service/cloudfront/command/function/sim-cf-list-functions.d.ts +22 -0
- package/dist/service/cloudfront/command/function/sim-cf-list-functions.js +38 -0
- package/dist/service/cloudfront/command/update-distribution/update-distribution.handler.d.ts +2 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-cache-policy.d.ts +18 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-cache-policy.js +30 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-policies.d.ts +28 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-policies.js +41 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-properties.d.ts +2 -2
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-properties.js +6 -3
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-response-headers-policy.d.ts +0 -10
- package/dist/service/cloudfront/distribution/configurator/sim-cf-behavior-response-headers-policy.js +0 -19
- package/dist/service/cloudfront/distribution/configurator/sim-cf-distribution-configurator.factory.d.ts +2 -0
- package/dist/service/cloudfront/distribution/configurator/sim-cf-distribution-configurator.factory.js +4 -2
- package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-behavior-configurator.d.ts +3 -3
- package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-behavior-configurator.js +5 -5
- package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-distribution-configurator.d.ts +3 -3
- package/dist/service/cloudfront/distribution/configurator/sim-cloud-front-distribution-configurator.js +4 -4
- package/dist/service/cloudfront/distribution/sim-cf-distribution-configuration-state.d.ts +3 -1
- package/dist/service/cloudfront/distribution/sim-cf-distribution-reconfigurer.d.ts +2 -0
- package/dist/service/cloudfront/error/sim-cloudfront.error.d.ts +21 -0
- package/dist/service/cloudfront/error/sim-cloudfront.error.js +25 -0
- package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store-access.js +2 -10
- package/dist/service/cloudfront/key-value-store/sim-cf-key-value-store.js +2 -1
- package/dist/service/cloudfront/sdk/sim-cloudfront-sdk-command-router.js +12 -0
- package/dist/service/cloudfront/sim-cf-authorize.d.ts +16 -0
- package/dist/service/cloudfront/sim-cf-authorize.js +19 -0
- package/dist/service/cloudfront/sim-cf-etag.d.ts +7 -0
- package/dist/service/cloudfront/sim-cf-etag.js +10 -0
- package/dist/service/cloudfront/sim-cloudfront-commands.d.ts +8 -12
- package/dist/service/cloudfront/sim-cloudfront-commands.js +8 -17
- package/dist/service/cloudfront/sim-cloudfront-policies.d.ts +43 -0
- package/dist/service/cloudfront/sim-cloudfront-policies.js +53 -0
- package/dist/service/cloudfront/sim-cloudfront.d.ts +13 -17
- package/dist/service/cloudfront/sim-cloudfront.js +22 -25
- package/dist/service/ecr/authorize/sim-ecr-authorizer.d.ts +31 -0
- package/dist/service/ecr/authorize/sim-ecr-authorizer.js +38 -0
- package/dist/service/ecr/cfn/repository/sim-cfn-ecr-repository-creator.d.ts +11 -2
- package/dist/service/ecr/cfn/repository/sim-cfn-ecr-repository-creator.js +11 -2
- package/dist/service/ecr/cfn/sim-ecr-cfn-resource-factory.d.ts +4 -2
- package/dist/service/ecr/cfn/sim-ecr-cfn-resource-factory.js +8 -9
- package/dist/service/ecr/cfn/sim-ecr-cfn-unsupported-resource.d.ts +7 -0
- package/dist/service/ecr/cfn/sim-ecr-cfn-unsupported-resource.js +9 -0
- package/dist/service/ecr/sim-ecr.d.ts +7 -0
- package/dist/service/ecr/sim-ecr.js +16 -4
- package/dist/service/ecs/command/authorize/sim-ecs-authorizer.d.ts +12 -0
- package/dist/service/ecs/command/authorize/sim-ecs-authorizer.js +21 -0
- package/dist/service/ecs/command/register-task-definition/register-task-definition.handler.js +1 -0
- package/dist/service/ecs/sim-ecs-service-principal.d.ts +8 -0
- package/dist/service/ecs/sim-ecs-service-principal.js +8 -0
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.d.ts +12 -0
- package/dist/service/eventbridge/command/authorize/sim-event-bridge-authorizer.js +21 -0
- package/dist/service/eventbridge/command/rule/sim-event-bridge-rule-access.d.ts +13 -0
- package/dist/service/eventbridge/command/rule/sim-event-bridge-rule-access.js +9 -0
- package/dist/service/eventbridge/command/target/sim-event-bridge-put-targets.js +1 -0
- package/dist/service/firehose/command/authorize/sim-firehose-authorizer.d.ts +12 -0
- package/dist/service/firehose/command/authorize/sim-firehose-authorizer.js +20 -0
- package/dist/service/firehose/command/sim-firehose-delivery-stream-access.d.ts +4 -0
- package/dist/service/firehose/command/sim-firehose-delivery-stream-access.js +6 -0
- package/dist/service/firehose/command/stream/sim-firehose-create-delivery-stream.js +3 -1
- package/dist/service/firehose/sim-firehose-service-principal.d.ts +8 -0
- package/dist/service/firehose/sim-firehose-service-principal.js +8 -0
- package/dist/service/firehose/source/sim-firehose-source.d.ts +5 -0
- package/dist/service/firehose/source/sim-firehose-source.js +5 -0
- package/dist/service/glue/cfn/database/sim-cfn-glue-database-properties.js +2 -2
- package/dist/service/glue/cfn/sim-cfn-glue-generated-name.d.ts +10 -0
- package/dist/service/glue/cfn/sim-cfn-glue-generated-name.js +25 -0
- package/dist/service/glue/cfn/table/sim-cfn-glue-table-properties.js +2 -3
- package/dist/service/iam/authorize/allow/sim-iam-allow-requirement.d.ts +33 -2
- package/dist/service/iam/authorize/allow/sim-iam-allow-requirement.js +33 -2
- package/dist/service/iam/authorize/allow/sim-iam-allow-statements.d.ts +4 -3
- package/dist/service/iam/authorize/allow/sim-iam-allow-statements.js +9 -3
- package/dist/service/iam/authorize/context/sim-iam-auth-z-allow-requirement.d.ts +14 -5
- package/dist/service/iam/authorize/context/sim-iam-auth-z-allow-requirement.js +16 -12
- package/dist/service/iam/authorize/context/sim-iam-auth-z-caller-context-builder.d.ts +36 -7
- package/dist/service/iam/authorize/context/sim-iam-auth-z-caller-context-builder.js +22 -11
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.d.ts +10 -71
- package/dist/service/iam/authorize/context/sim-iam-auth-z-context-builder.js +7 -2
- package/dist/service/iam/authorize/context/sim-iam-auth-z-input.d.ts +87 -0
- package/dist/service/iam/authorize/context/sim-iam-auth-z-input.js +1 -0
- package/dist/service/iam/authorize/match/sim-iam-policy-principal-matcher.d.ts +21 -3
- package/dist/service/iam/authorize/match/sim-iam-policy-principal-matcher.js +34 -10
- package/dist/service/iam/authorize/match/sim-iam-principal-match.d.ts +29 -8
- package/dist/service/iam/authorize/match/sim-iam-principal-match.js +38 -13
- package/dist/service/iam/authorize/pass-role/sim-iam-pass-role-authorizer.d.ts +74 -0
- package/dist/service/iam/authorize/pass-role/sim-iam-pass-role-authorizer.js +92 -0
- package/dist/service/iam/authorize/sim-iam-account-auth-z.d.ts +21 -5
- package/dist/service/iam/authorize/sim-iam-account-auth-z.js +7 -3
- package/dist/service/iam/authorize/sim-iam-authorizer.d.ts +5 -2
- package/dist/service/iam/authorize/sim-iam-authorizer.js +3 -1
- package/dist/service/iam/authorize/sim-iam-inter-service-auth-z.d.ts +1 -1
- package/dist/service/iam/authorize/sim-iam-wildcard.js +39 -4
- package/dist/service/iam/cfn/managed-policy/sim-cfn-iam-managed-policy-creator.js +2 -1
- package/dist/service/iam/cfn/name/sim-cfn-iam-generated-name.d.ts +16 -0
- package/dist/service/iam/cfn/name/sim-cfn-iam-generated-name.js +36 -0
- package/dist/service/iam/cfn/role/sim-cfn-iam-role-properties-parser.js +9 -8
- package/dist/service/iam/cfn/sim-cfn-iam-optional-string.d.ts +17 -0
- package/dist/service/iam/cfn/sim-cfn-iam-optional-string.js +17 -0
- package/dist/service/iam/cfn/user/sim-cfn-iam-user-properties-parser.js +4 -8
- package/dist/service/iam/command/policy/create-policy/create-policy-input-resolver.js +2 -0
- package/dist/service/iam/command/policy/put-role-policy/put-role-policy.handler.js +5 -0
- package/dist/service/iam/command/policy/put-user-policy/put-user-policy.handler.js +5 -0
- package/dist/service/iam/command/role/create-role/create-role.handler.js +4 -1
- package/dist/service/iam/error/sim-iam.error.d.ts +11 -0
- package/dist/service/iam/error/sim-iam.error.js +13 -0
- package/dist/service/iam/index.d.ts +1 -0
- package/dist/service/iam/policy/sim-iam-policy-document-of-size.d.ts +18 -0
- package/dist/service/iam/policy/sim-iam-policy-document-of-size.js +41 -0
- package/dist/service/iam/role/sim-iam-deploy-role.d.ts +56 -0
- package/dist/service/iam/role/sim-iam-deploy-role.js +50 -0
- package/dist/service/iam/role/sim-iam-role-with-policy.factory.d.ts +11 -0
- package/dist/service/iam/role/sim-iam-role-with-policy.factory.js +4 -2
- package/dist/service/iam/sim-iam-account-parts.d.ts +16 -0
- package/dist/service/iam/sim-iam-account-parts.js +2 -0
- package/dist/service/iam/sim-iam.d.ts +12 -2
- package/dist/service/iam/sim-iam.js +12 -0
- package/dist/service/iam/validate/size/sim-iam-policy-document-size.d.ts +57 -0
- package/dist/service/iam/validate/size/sim-iam-policy-document-size.js +71 -0
- package/dist/service/kms/command/authorize/sim-kms-authorizer.d.ts +3 -1
- package/dist/service/kms/command/authorize/sim-kms-authorizer.js +4 -1
- package/dist/service/kms/command/sim-kms-request-options.d.ts +11 -0
- package/dist/service/kms/key/sim-kms-key-policy.d.ts +5 -4
- package/dist/service/kms/key/sim-kms-key-policy.js +4 -3
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-function-properties-parser.d.ts +2 -2
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-function-properties-parser.js +4 -3
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-generated-function-name.d.ts +10 -0
- package/dist/service/lambda/cfn/function/sim-cfn-lambda-generated-function-name.js +25 -0
- package/dist/service/lambda/command/authorize/sim-lambda-resource-policies.d.ts +1 -1
- package/dist/service/lambda/command/create-function/create-function-authorizer.d.ts +9 -2
- package/dist/service/lambda/command/create-function/create-function-authorizer.js +16 -2
- package/dist/service/lambda/command/create-function/create-function.handler.js +1 -1
- package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.d.ts +7 -2
- package/dist/service/lambda/command/update-function-configuration/update-function-configuration-authorizer.js +14 -2
- package/dist/service/lambda/command/update-function-configuration/update-function-configuration.handler.js +1 -1
- package/dist/service/lambda/function/logging/sim-lambda-function-logging.d.ts +10 -1
- package/dist/service/lambda/function/logging/sim-lambda-function-logging.js +25 -1
- package/dist/service/lambda/function/logging/sim-lambda-invoke-error-log.d.ts +13 -0
- package/dist/service/lambda/function/logging/sim-lambda-invoke-error-log.js +18 -0
- package/dist/service/lambda/sim-lambda-service-principal.d.ts +7 -0
- package/dist/service/lambda/sim-lambda-service-principal.js +7 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-authorization.d.ts +46 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-authorization.js +49 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-creator.d.ts +5 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-creator.js +6 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-destination-creator.d.ts +5 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-destination-creator.js +6 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-source-creator.d.ts +5 -0
- package/dist/service/logs/cfn/delivery/sim-cfn-delivery-source-creator.js +6 -0
- package/dist/service/logs/cfn/group/sim-cfn-log-group-creator.d.ts +9 -2
- package/dist/service/logs/cfn/group/sim-cfn-log-group-creator.js +34 -5
- package/dist/service/logs/cfn/sim-logs-cfn-resource-deleter.js +1 -1
- package/dist/service/logs/cfn/sim-logs-cfn-resource-factory.d.ts +4 -0
- package/dist/service/logs/cfn/sim-logs-cfn-resource-factory.js +9 -4
- package/dist/service/logs/sim-logs-commands.d.ts +3 -0
- package/dist/service/logs/sim-logs-commands.js +4 -0
- package/dist/service/logs/sim-logs.js +6 -1
- package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-creator.d.ts +2 -2
- package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-creator.js +4 -3
- package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-generated-name.d.ts +12 -0
- package/dist/service/s3/cfn/bucket/sim-cfn-s3-bucket-generated-name.js +22 -0
- package/dist/service/s3/command/authorize/sim-s3-bucket-resource-policies.d.ts +1 -1
- package/dist/service/scheduler/command/authorize/sim-scheduler-authorizer.d.ts +10 -1
- package/dist/service/scheduler/command/authorize/sim-scheduler-authorizer.js +19 -1
- package/dist/service/scheduler/command/schedule/sim-scheduler-create-schedule.js +1 -0
- package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-access.d.ts +8 -0
- package/dist/service/scheduler/command/schedule/sim-scheduler-schedule-access.js +9 -0
- package/dist/service/scheduler/command/schedule/sim-scheduler-update-schedule.js +1 -0
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-generated-name.d.ts +15 -0
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-generated-name.js +22 -0
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-properties.d.ts +4 -10
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-properties.js +13 -31
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-value.d.ts +17 -0
- package/dist/service/secretsmanager/cfn/secret/sim-cfn-secrets-manager-secret-value.js +30 -0
- package/dist/service/secretsmanager/secret/sim-secrets-manager-secret-name.d.ts +6 -0
- package/dist/service/secretsmanager/secret/sim-secrets-manager-secret-name.js +8 -3
- package/dist/service/sns/command/authorize/sim-sns-topic-resource-policies.d.ts +1 -1
- package/dist/service/sqs/command/authorize/sim-sqs-queue-resource-policies.d.ts +1 -1
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-generated-parameter-name.d.ts +16 -0
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-generated-parameter-name.js +23 -0
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.d.ts +2 -4
- package/dist/service/ssm/cfn/parameter/sim-cfn-ssm-parameter-properties.js +5 -5
- package/dist/service/ssm/parameter/sim-ssm-kms-crypto.d.ts +6 -4
- package/dist/service/ssm/parameter/sim-ssm-kms-crypto.js +4 -4
- package/dist/service/ssm/parameter/sim-ssm-parameter-arn.d.ts +17 -0
- package/dist/service/ssm/parameter/sim-ssm-parameter-arn.js +20 -0
- package/dist/service/ssm/parameter/sim-ssm-parameter-kms.d.ts +15 -9
- package/dist/service/ssm/parameter/sim-ssm-parameter-kms.js +20 -10
- package/dist/service/ssm/parameter/sim-ssm-parameter-name.js +3 -12
- package/dist/service/stepfunctions/command/authorize/sim-step-functions-authorizer.d.ts +41 -0
- package/dist/service/stepfunctions/command/authorize/sim-step-functions-authorizer.js +64 -0
- package/dist/service/stepfunctions/command/machine/sim-state-machine-create.d.ts +5 -2
- package/dist/service/stepfunctions/command/machine/sim-state-machine-create.js +6 -2
- package/dist/service/stepfunctions/command/machine/sim-state-machine-delete.d.ts +26 -0
- package/dist/service/stepfunctions/command/machine/sim-state-machine-delete.js +29 -0
- package/dist/service/stepfunctions/command/machine/sim-state-machine-lookup.d.ts +7 -0
- package/dist/service/stepfunctions/command/machine/sim-state-machine-lookup.js +12 -3
- package/dist/service/stepfunctions/command/machine/sim-state-machine-update.d.ts +19 -0
- package/dist/service/stepfunctions/command/machine/{sim-state-machine-writes.js → sim-state-machine-update.js} +3 -14
- package/dist/service/stepfunctions/sim-step-functions.d.ts +8 -2
- package/dist/service/stepfunctions/sim-step-functions.js +26 -9
- package/dist/service/sts/auth-z/assume-role-auth-z-coordinator.d.ts +9 -2
- package/dist/service/sts/auth-z/assume-role-auth-z-coordinator.js +2 -2
- package/dist/service/sts/auth-z/assume-role-source-account-auth-z.d.ts +10 -4
- package/dist/service/sts/auth-z/assume-role-source-account-auth-z.js +8 -7
- package/dist/service/sts/auth-z/assume-role-target-auth-z.d.ts +2 -2
- package/dist/service/sts/auth-z/assume-role-trust-policy-authorizer.d.ts +6 -2
- package/dist/service/sts/auth-z/assume-role-trust-policy-authorizer.js +14 -11
- package/dist/service/sts/command/assume-role/assume-role.handler.d.ts +10 -1
- package/dist/service/sts/command/assume-role/assume-role.handler.js +6 -2
- package/dist/service/sts/command/get-caller-identity/get-caller-identity.handler.d.ts +10 -1
- package/dist/service/sts/command/get-caller-identity/get-caller-identity.handler.js +5 -1
- package/dist/service/sts/service-role/sim-service-role.js +5 -1
- package/dist/service/sts/sim-sts.d.ts +18 -1
- package/dist/service/sts/sim-sts.js +8 -0
- package/dist/util/memo/bounded-memo.d.ts +36 -0
- package/dist/util/memo/bounded-memo.js +58 -0
- package/docs/README.md +54 -0
- package/docs/ai-skill/README.md +69 -0
- package/docs/cli/README.md +284 -0
- package/docs/factories/README.md +140 -0
- package/docs/lint/README.md +176 -0
- package/docs/non-aws-dependencies/README.md +261 -0
- package/docs/sdk/README.md +274 -0
- package/docs/serve/README.md +1126 -0
- package/docs/services/acm/README.md +823 -0
- package/docs/services/apigateway/README.md +1919 -0
- package/docs/services/apigatewayv2/README.md +2678 -0
- package/docs/services/athena/README.md +1044 -0
- package/docs/services/bedrock/README.md +350 -0
- package/docs/services/cloudformation/README.md +3625 -0
- package/docs/services/cloudfront/README.md +3098 -0
- package/docs/services/cloudwatch/README.md +422 -0
- package/docs/services/cognito/README.md +4924 -0
- package/docs/services/dynamodb/README.md +3785 -0
- package/docs/services/ecr/README.md +302 -0
- package/docs/services/ecs/README.md +2021 -0
- package/docs/services/elbv2/README.md +1901 -0
- package/docs/services/eventbridge/README.md +1118 -0
- package/docs/services/firehose/README.md +811 -0
- package/docs/services/glue/README.md +507 -0
- package/docs/services/iam/README.md +1578 -0
- package/docs/services/kinesis/README.md +455 -0
- package/docs/services/kms/README.md +664 -0
- package/docs/services/lambda/README.md +3719 -0
- package/docs/services/logs/README.md +882 -0
- package/docs/services/organizations/README.md +574 -0
- package/docs/services/personalize/README.md +835 -0
- package/docs/services/rekognition/README.md +1070 -0
- package/docs/services/route53/README.md +1783 -0
- package/docs/services/s3/README.md +3029 -0
- package/docs/services/scheduler/README.md +814 -0
- package/docs/services/secretsmanager/README.md +670 -0
- package/docs/services/ses/README.md +1013 -0
- package/docs/services/sns/README.md +1904 -0
- package/docs/services/sqs/README.md +1185 -0
- package/docs/services/ssm/README.md +1096 -0
- package/docs/services/stepfunctions/README.md +1341 -0
- package/docs/services/sts/README.md +245 -0
- package/docs/services/wafv2/README.md +1380 -0
- package/docs/terraform/README.md +248 -0
- package/docs/time/README.md +284 -0
- package/llms.txt +59 -0
- package/package.json +7 -4
- package/dist/service/stepfunctions/command/machine/sim-state-machine-writes.d.ts +0 -25
|
@@ -0,0 +1,1185 @@
|
|
|
1
|
+
# Simulated SQS
|
|
2
|
+
|
|
3
|
+
Yulin includes a simulated Amazon SQS for tests and local development. Messages are held in memory,
|
|
4
|
+
hidden and released on the simulation's own clock, and every operation is authorized by simulated IAM.
|
|
5
|
+
|
|
6
|
+
Standard queues only. SQS-specific types are imported from the `@kensio/yulin/sqs` subpath.
|
|
7
|
+
|
|
8
|
+
## Creating a queue and sending a message
|
|
9
|
+
|
|
10
|
+
```typescript sim-sqs-send-and-receive
|
|
11
|
+
/**
|
|
12
|
+
* Sending a message to a simulated queue and receiving it.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
CreateQueueCommand,
|
|
17
|
+
DeleteMessageCommand,
|
|
18
|
+
ReceiveMessageCommand,
|
|
19
|
+
SendMessageCommand,
|
|
20
|
+
} from "@aws-sdk/client-sqs";
|
|
21
|
+
|
|
22
|
+
import { SimAws } from "@kensio/yulin";
|
|
23
|
+
|
|
24
|
+
const simAws = new SimAws();
|
|
25
|
+
const sqs = simAws.sqs();
|
|
26
|
+
|
|
27
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
28
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
await sqs.sendMessage(
|
|
32
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const received = await sqs.receiveMessage(
|
|
36
|
+
new ReceiveMessageCommand({ QueueUrl }),
|
|
37
|
+
);
|
|
38
|
+
const message = received.Messages?.[0];
|
|
39
|
+
|
|
40
|
+
console.log(message?.Body); // "order-1"
|
|
41
|
+
|
|
42
|
+
await sqs.deleteMessage(
|
|
43
|
+
new DeleteMessageCommand({
|
|
44
|
+
QueueUrl,
|
|
45
|
+
ReceiptHandle: message?.ReceiptHandle,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A queue URL is `https://sqs.<region>.amazonaws.com/<account-id>/<name>`, and the ARN is
|
|
51
|
+
`arn:aws:sqs:<region>:<account-id>:<name>`. An SQS ARN has no resource type in it. The queue name
|
|
52
|
+
follows the account id directly.
|
|
53
|
+
|
|
54
|
+
`CreateQueue` is idempotent, as it is on real AWS. A second request for the same name returns the
|
|
55
|
+
existing queue's URL when the attributes it names match, and fails with `QueueNameExists` when they
|
|
56
|
+
differ. A request naming no attributes always matches.
|
|
57
|
+
|
|
58
|
+
## Visibility timeouts
|
|
59
|
+
|
|
60
|
+
A received message is hidden from other consumers for the queue's visibility timeout, 30 seconds by
|
|
61
|
+
default. The message records the instant it is hidden until. It becomes receivable again once
|
|
62
|
+
simulated time reaches that instant. Advancing the clock is all a test needs to watch an undeleted
|
|
63
|
+
message come back.
|
|
64
|
+
|
|
65
|
+
```typescript sim-sqs-visibility-timeout
|
|
66
|
+
/**
|
|
67
|
+
* A message that was received but never deleted, coming back once its
|
|
68
|
+
* visibility timeout lapses.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
import {
|
|
72
|
+
CreateQueueCommand,
|
|
73
|
+
ReceiveMessageCommand,
|
|
74
|
+
SendMessageCommand,
|
|
75
|
+
} from "@aws-sdk/client-sqs";
|
|
76
|
+
|
|
77
|
+
import { SimAws } from "@kensio/yulin";
|
|
78
|
+
|
|
79
|
+
const simAws = new SimAws();
|
|
80
|
+
const sqs = simAws.sqs();
|
|
81
|
+
|
|
82
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
83
|
+
new CreateQueueCommand({
|
|
84
|
+
QueueName: "orders",
|
|
85
|
+
Attributes: { VisibilityTimeout: "30" },
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
await sqs.sendMessage(
|
|
90
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const first = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
94
|
+
|
|
95
|
+
console.log(first.Messages?.length); // 1
|
|
96
|
+
|
|
97
|
+
// The message is invisible to everyone else while the timeout runs.
|
|
98
|
+
const empty = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
99
|
+
|
|
100
|
+
console.log(empty.Messages); // undefined
|
|
101
|
+
|
|
102
|
+
await simAws.clock().advanceBy({ seconds: 31 });
|
|
103
|
+
|
|
104
|
+
const again = await sqs.receiveMessage(
|
|
105
|
+
new ReceiveMessageCommand({
|
|
106
|
+
QueueUrl,
|
|
107
|
+
MessageSystemAttributeNames: ["ApproximateReceiveCount"],
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
console.log(again.Messages?.[0]?.Attributes?.["ApproximateReceiveCount"]); // "2"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
A receive request can override the timeout for the messages it takes with `VisibilityTimeout`, and a
|
|
115
|
+
consumer part way through a slow handler can ask for more time with `ChangeMessageVisibility`. The
|
|
116
|
+
new timeout runs from the moment of the change rather than from the receive, as it does on real AWS.
|
|
117
|
+
A timeout of zero gives the message straight back to the queue.
|
|
118
|
+
|
|
119
|
+
`ChangeMessageVisibility` on a message whose timeout has already lapsed fails with
|
|
120
|
+
`MessageNotInflight`. There is no timeout left to change, and real SQS answers the same way.
|
|
121
|
+
|
|
122
|
+
See [simulated time](https://yulinsim.dev/time/ "Simulated time docs") for what else the clock can do.
|
|
123
|
+
|
|
124
|
+
## Receipt handles
|
|
125
|
+
|
|
126
|
+
Every receive issues a fresh receipt handle, and a delete has to use the handle from the most recent
|
|
127
|
+
receive of that message. A handle from an earlier receive is accepted and deletes nothing. Real SQS
|
|
128
|
+
accepts one too, and promises only that the message might not be deleted.
|
|
129
|
+
|
|
130
|
+
That is the failure a consumer slower than its visibility timeout hits. Its message went back on the
|
|
131
|
+
queue, someone else took it, and its own delete quietly does nothing.
|
|
132
|
+
|
|
133
|
+
```typescript sim-sqs-stale-receipt-handle
|
|
134
|
+
/**
|
|
135
|
+
* A slow consumer deleting with a receipt handle another receive has
|
|
136
|
+
* superseded.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
import {
|
|
140
|
+
CreateQueueCommand,
|
|
141
|
+
DeleteMessageCommand,
|
|
142
|
+
ReceiveMessageCommand,
|
|
143
|
+
SendMessageCommand,
|
|
144
|
+
} from "@aws-sdk/client-sqs";
|
|
145
|
+
|
|
146
|
+
import { SimAws } from "@kensio/yulin";
|
|
147
|
+
|
|
148
|
+
const simAws = new SimAws();
|
|
149
|
+
const sqs = simAws.sqs();
|
|
150
|
+
|
|
151
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
152
|
+
new CreateQueueCommand({
|
|
153
|
+
QueueName: "orders",
|
|
154
|
+
Attributes: { VisibilityTimeout: "30" },
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
await sqs.sendMessage(
|
|
159
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const slow = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
163
|
+
|
|
164
|
+
// The slow consumer takes longer than the visibility timeout, and another
|
|
165
|
+
// consumer receives the message in the meantime.
|
|
166
|
+
await simAws.clock().advanceBy({ seconds: 31 });
|
|
167
|
+
await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
168
|
+
|
|
169
|
+
// The delete succeeds and deletes nothing.
|
|
170
|
+
await sqs.deleteMessage(
|
|
171
|
+
new DeleteMessageCommand({
|
|
172
|
+
QueueUrl,
|
|
173
|
+
ReceiptHandle: slow.Messages?.[0]?.ReceiptHandle,
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
await simAws.clock().advanceBy({ seconds: 31 });
|
|
178
|
+
|
|
179
|
+
const still = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
180
|
+
|
|
181
|
+
console.log(still.Messages?.[0]?.Body); // "order-1"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
A handle whose visibility timeout has lapsed with nobody else having received the message since is
|
|
185
|
+
still the most recent one, so deleting with it works. A handle the queue never issued fails with
|
|
186
|
+
`ReceiptHandleIsInvalid`, and a repeated delete of a message already gone succeeds.
|
|
187
|
+
|
|
188
|
+
## Dead-letter queues
|
|
189
|
+
|
|
190
|
+
A `RedrivePolicy` says where a message goes once a consumer has had enough attempts at it. Once a
|
|
191
|
+
message has been received `maxReceiveCount` times without being deleted, the next lapse of its
|
|
192
|
+
visibility timeout moves it to the queue named by `deadLetterTargetArn`. Advancing the clock drives
|
|
193
|
+
the move, as it drives the timeout itself.
|
|
194
|
+
|
|
195
|
+
```typescript sim-sqs-dead-letter-queue
|
|
196
|
+
/**
|
|
197
|
+
* A message a consumer keeps failing on, ending up on the dead-letter queue.
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
import {
|
|
201
|
+
CreateQueueCommand,
|
|
202
|
+
GetQueueAttributesCommand,
|
|
203
|
+
ReceiveMessageCommand,
|
|
204
|
+
SendMessageCommand,
|
|
205
|
+
} from "@aws-sdk/client-sqs";
|
|
206
|
+
|
|
207
|
+
import { SimAws } from "@kensio/yulin";
|
|
208
|
+
|
|
209
|
+
const simAws = new SimAws();
|
|
210
|
+
const sqs = simAws.sqs();
|
|
211
|
+
|
|
212
|
+
// The dead-letter queue has to exist before anything can point at it.
|
|
213
|
+
const { QueueUrl: DeadLetterQueueUrl } = await sqs.createQueue(
|
|
214
|
+
new CreateQueueCommand({ QueueName: "orders-dlq" }),
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const deadLetter = await sqs.getQueueAttributes(
|
|
218
|
+
new GetQueueAttributesCommand({
|
|
219
|
+
QueueUrl: DeadLetterQueueUrl,
|
|
220
|
+
AttributeNames: ["QueueArn"],
|
|
221
|
+
}),
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
225
|
+
new CreateQueueCommand({
|
|
226
|
+
QueueName: "orders",
|
|
227
|
+
Attributes: {
|
|
228
|
+
VisibilityTimeout: "30",
|
|
229
|
+
RedrivePolicy: JSON.stringify({
|
|
230
|
+
deadLetterTargetArn: deadLetter.Attributes?.["QueueArn"],
|
|
231
|
+
maxReceiveCount: 3,
|
|
232
|
+
}),
|
|
233
|
+
},
|
|
234
|
+
}),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
await sqs.sendMessage(
|
|
238
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// A consumer takes the message and never gets as far as deleting it.
|
|
242
|
+
async function failToHandleMessage(): Promise<void> {
|
|
243
|
+
await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
244
|
+
await simAws.clock().advanceBy({ seconds: 31 });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
await failToHandleMessage();
|
|
248
|
+
await failToHandleMessage();
|
|
249
|
+
await failToHandleMessage();
|
|
250
|
+
|
|
251
|
+
// The source queue has given up on it.
|
|
252
|
+
const empty = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
253
|
+
|
|
254
|
+
console.log(empty.Messages); // undefined
|
|
255
|
+
|
|
256
|
+
const dead = await sqs.receiveMessage(
|
|
257
|
+
new ReceiveMessageCommand({ QueueUrl: DeadLetterQueueUrl }),
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
console.log(dead.Messages?.[0]?.Body); // "order-1"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The message keeps its `MessageId`, body and message attributes, and a test can identify it by any of
|
|
264
|
+
them. `ApproximateNumberOfMessages` on both queues reflects the move. A message deleted before its
|
|
265
|
+
attempts run out never gets there, and a message still inside its visibility timeout has not moved
|
|
266
|
+
yet, because the consumer holding it may still delete it.
|
|
267
|
+
|
|
268
|
+
`SentTimestamp` is unchanged by the move, as it is on a real standard queue. The dead-letter queue's
|
|
269
|
+
`MessageRetentionPeriod` therefore runs from when the message was first sent. That is why AWS
|
|
270
|
+
suggests giving a dead-letter queue a longer retention period than the queue feeding it.
|
|
271
|
+
`ApproximateReceiveCount` starts again from one, since a receive count counts receives from one queue
|
|
272
|
+
and the message has not been received from this one yet. A moved message also reports
|
|
273
|
+
`DeadLetterQueueSourceArn`, naming the queue it came from.
|
|
274
|
+
|
|
275
|
+
The policy is validated when it is set, whether by `CreateQueue` or `SetQueueAttributes`. It has to
|
|
276
|
+
be a JSON object with both a `deadLetterTargetArn` and a `maxReceiveCount` between 1 and 1000,
|
|
277
|
+
carried as a JSON number or as a string holding one. The `deadLetterTargetArn` has to name a queue
|
|
278
|
+
that already exists in the same account and region, as real SQS requires. A policy pointing at
|
|
279
|
+
nothing fails there and then, before a message has been lost to it. Anything else fails with
|
|
280
|
+
`InvalidParameterValue`.
|
|
281
|
+
|
|
282
|
+
`GetQueueAttributes` reports `RedrivePolicy` back as the string it was set with.
|
|
283
|
+
|
|
284
|
+
## Delays
|
|
285
|
+
|
|
286
|
+
`DelaySeconds` hides a new message until it lapses, either set on the queue for every message or on
|
|
287
|
+
one message as it is sent.
|
|
288
|
+
|
|
289
|
+
```typescript sim-sqs-delayed-message
|
|
290
|
+
/**
|
|
291
|
+
* A message that cannot be received until the delay it was sent with lapses.
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
import {
|
|
295
|
+
CreateQueueCommand,
|
|
296
|
+
ReceiveMessageCommand,
|
|
297
|
+
SendMessageCommand,
|
|
298
|
+
} from "@aws-sdk/client-sqs";
|
|
299
|
+
|
|
300
|
+
import { SimAws } from "@kensio/yulin";
|
|
301
|
+
|
|
302
|
+
const simAws = new SimAws();
|
|
303
|
+
const sqs = simAws.sqs();
|
|
304
|
+
|
|
305
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
306
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
await sqs.sendMessage(
|
|
310
|
+
new SendMessageCommand({
|
|
311
|
+
QueueUrl,
|
|
312
|
+
MessageBody: "order-1",
|
|
313
|
+
DelaySeconds: 60,
|
|
314
|
+
}),
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const early = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
318
|
+
|
|
319
|
+
console.log(early.Messages); // undefined
|
|
320
|
+
|
|
321
|
+
await simAws.clock().advanceBy({ seconds: 61 });
|
|
322
|
+
|
|
323
|
+
const late = await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
324
|
+
|
|
325
|
+
console.log(late.Messages?.[0]?.Body); // "order-1"
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`MessageRetentionPeriod` works on the same clock. A message on the queue for longer than the
|
|
329
|
+
retention period (four days by default) is gone.
|
|
330
|
+
|
|
331
|
+
## Message attributes
|
|
332
|
+
|
|
333
|
+
Message attributes round-trip, and both digests are computed. `MD5OfMessageBody` is an MD5 of the
|
|
334
|
+
body, and `MD5OfMessageAttributes` uses the length-prefixed encoding real SQS digests attributes
|
|
335
|
+
with. A consumer checking either against its own digest is checking a real MD5.
|
|
336
|
+
|
|
337
|
+
A receive returns no attributes unless it names them, as on real AWS. `All` or `.*` selects every
|
|
338
|
+
attribute, a bare name selects one, and a name ending in `.*` selects a prefix.
|
|
339
|
+
|
|
340
|
+
```typescript sim-sqs-message-attributes
|
|
341
|
+
/**
|
|
342
|
+
* Message attributes on a simulated queue, and asking for them back.
|
|
343
|
+
*/
|
|
344
|
+
|
|
345
|
+
import {
|
|
346
|
+
CreateQueueCommand,
|
|
347
|
+
ReceiveMessageCommand,
|
|
348
|
+
SendMessageCommand,
|
|
349
|
+
} from "@aws-sdk/client-sqs";
|
|
350
|
+
|
|
351
|
+
import { SimAws } from "@kensio/yulin";
|
|
352
|
+
|
|
353
|
+
const simAws = new SimAws();
|
|
354
|
+
const sqs = simAws.sqs();
|
|
355
|
+
|
|
356
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
357
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
const sent = await sqs.sendMessage(
|
|
361
|
+
new SendMessageCommand({
|
|
362
|
+
QueueUrl,
|
|
363
|
+
MessageBody: "order-1",
|
|
364
|
+
MessageAttributes: {
|
|
365
|
+
tenant: { DataType: "String", StringValue: "acme" },
|
|
366
|
+
attempt: { DataType: "Number", StringValue: "1" },
|
|
367
|
+
},
|
|
368
|
+
}),
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
const received = await sqs.receiveMessage(
|
|
372
|
+
new ReceiveMessageCommand({ QueueUrl, MessageAttributeNames: ["All"] }),
|
|
373
|
+
);
|
|
374
|
+
const message = received.Messages?.[0];
|
|
375
|
+
|
|
376
|
+
console.log(message?.MessageAttributes?.["tenant"]?.StringValue); // "acme"
|
|
377
|
+
console.log(message?.MD5OfMessageAttributes === sent.MD5OfMessageAttributes); // true
|
|
378
|
+
console.log(message?.MD5OfBody === sent.MD5OfMessageBody); // true
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
The name and data type rules are the real ones. A data type is `String`, `Number` or `Binary`, and
|
|
382
|
+
each takes a custom label after a dot, so `Number.int` is a number as far as the rules go. A
|
|
383
|
+
reserved `AWS.` or `Amazon.` prefix on a name, a data type built on none of the three, or a value
|
|
384
|
+
that disagrees with its data type is refused. A test finds any of those without going near AWS.
|
|
385
|
+
|
|
386
|
+
The message system attributes are asked for separately, with `MessageSystemAttributeNames`, or with
|
|
387
|
+
the discontinued `AttributeNames` that means the same thing. `SentTimestamp`,
|
|
388
|
+
`ApproximateReceiveCount` and `ApproximateFirstReceiveTimestamp` are reported.
|
|
389
|
+
|
|
390
|
+
## Queue attributes
|
|
391
|
+
|
|
392
|
+
`GetQueueAttributes` returns only the attributes a request names, as real SQS does, and `All` names
|
|
393
|
+
every attribute this simulation holds. The defaults are the AWS ones. `VisibilityTimeout` is 30,
|
|
394
|
+
`DelaySeconds` 0, `MessageRetentionPeriod` 345600, `MaximumMessageSize` 262144 and
|
|
395
|
+
`ReceiveMessageWaitTimeSeconds` 0.
|
|
396
|
+
|
|
397
|
+
```typescript sim-sqs-queue-attributes
|
|
398
|
+
/**
|
|
399
|
+
* Reading the counts and settings of a simulated queue.
|
|
400
|
+
*/
|
|
401
|
+
|
|
402
|
+
import {
|
|
403
|
+
CreateQueueCommand,
|
|
404
|
+
GetQueueAttributesCommand,
|
|
405
|
+
ReceiveMessageCommand,
|
|
406
|
+
SendMessageCommand,
|
|
407
|
+
SetQueueAttributesCommand,
|
|
408
|
+
} from "@aws-sdk/client-sqs";
|
|
409
|
+
|
|
410
|
+
import { SimAws } from "@kensio/yulin";
|
|
411
|
+
|
|
412
|
+
const simAws = new SimAws();
|
|
413
|
+
const sqs = simAws.sqs();
|
|
414
|
+
|
|
415
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
416
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
await sqs.setQueueAttributes(
|
|
420
|
+
new SetQueueAttributesCommand({
|
|
421
|
+
QueueUrl,
|
|
422
|
+
Attributes: { VisibilityTimeout: "120" },
|
|
423
|
+
}),
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
await sqs.sendMessage(
|
|
427
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
428
|
+
);
|
|
429
|
+
await sqs.sendMessage(
|
|
430
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-2" }),
|
|
431
|
+
);
|
|
432
|
+
await sqs.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
433
|
+
|
|
434
|
+
const read = await sqs.getQueueAttributes(
|
|
435
|
+
new GetQueueAttributesCommand({ QueueUrl, AttributeNames: ["All"] }),
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
console.log(read.Attributes?.["VisibilityTimeout"]); // "120"
|
|
439
|
+
console.log(read.Attributes?.["ApproximateNumberOfMessages"]); // "1"
|
|
440
|
+
console.log(read.Attributes?.["ApproximateNumberOfMessagesNotVisible"]); // "1"
|
|
441
|
+
console.log(read.Attributes?.["QueueArn"]); // "arn:aws:sqs:us-east-1:888888888888:orders"
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
The other two settable attributes are JSON documents. `RedrivePolicy` is covered under
|
|
445
|
+
[dead-letter queues](#dead-letter-queues) above and `Policy` under
|
|
446
|
+
[queue policies](#queue-policies) below. Both are reported back as the string they were set with.
|
|
447
|
+
|
|
448
|
+
An attribute real SQS reports and this simulation does not model, `RedriveAllowPolicy` for one, is
|
|
449
|
+
left out of a response. Real SQS leaves out an attribute a queue has no value for in the same way.
|
|
450
|
+
Setting one is refused, because a queue that appeared to accept it would behave differently here than
|
|
451
|
+
on AWS.
|
|
452
|
+
|
|
453
|
+
`PurgeQueue` deletes everything on a queue, hidden messages included.
|
|
454
|
+
|
|
455
|
+
## IAM permissions
|
|
456
|
+
|
|
457
|
+
Every operation is authorized against the queue's ARN, which carries the queue name with no resource
|
|
458
|
+
type in front of it. Two details of real SQS trip policies up:
|
|
459
|
+
|
|
460
|
+
- `ListQueues` has no resource type at all. A policy allowing it names `*`. A policy naming one
|
|
461
|
+
queue, or every queue in the Account and Region, grants no listing.
|
|
462
|
+
- The batch operations are authorized as their singular action. There is no `sqs:SendMessageBatch`,
|
|
463
|
+
`sqs:DeleteMessageBatch` or `sqs:ChangeMessageVisibilityBatch` action for a policy to name.
|
|
464
|
+
|
|
465
|
+
The queue's own policy is part of the decision too, covered under [queue policies](#queue-policies)
|
|
466
|
+
below. A caller with no permission is refused whether or not the queue exists, since a queue that is
|
|
467
|
+
not there has no policy to admit anyone with.
|
|
468
|
+
|
|
469
|
+
```typescript sim-sqs-iam-policy
|
|
470
|
+
/**
|
|
471
|
+
* A Role allowed to consume from one simulated queue and nothing else.
|
|
472
|
+
*/
|
|
473
|
+
|
|
474
|
+
import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
|
|
475
|
+
import {
|
|
476
|
+
CreateQueueCommand,
|
|
477
|
+
ReceiveMessageCommand,
|
|
478
|
+
SendMessageCommand,
|
|
479
|
+
} from "@aws-sdk/client-sqs";
|
|
480
|
+
|
|
481
|
+
import { SimAws } from "@kensio/yulin";
|
|
482
|
+
|
|
483
|
+
const simAws = new SimAws();
|
|
484
|
+
const accountId = simAws.defaultAccountId;
|
|
485
|
+
const regionName = simAws.defaultRegionName;
|
|
486
|
+
const sqs = simAws.sqs();
|
|
487
|
+
|
|
488
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
489
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
await sqs.sendMessage(
|
|
493
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }),
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
const role = await simAws.iam().createRole(
|
|
497
|
+
new CreateRoleCommand({
|
|
498
|
+
RoleName: "OrderConsumer",
|
|
499
|
+
AssumeRolePolicyDocument: JSON.stringify({
|
|
500
|
+
Version: "2012-10-17",
|
|
501
|
+
Statement: {
|
|
502
|
+
Effect: "Allow",
|
|
503
|
+
Principal: { AWS: `arn:aws:iam::${accountId}:root` },
|
|
504
|
+
Action: "sts:AssumeRole",
|
|
505
|
+
},
|
|
506
|
+
}),
|
|
507
|
+
}),
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
await simAws.iam().putRolePolicy(
|
|
511
|
+
new PutRolePolicyCommand({
|
|
512
|
+
RoleName: "OrderConsumer",
|
|
513
|
+
PolicyName: "ConsumeOrders",
|
|
514
|
+
PolicyDocument: JSON.stringify({
|
|
515
|
+
Version: "2012-10-17",
|
|
516
|
+
Statement: {
|
|
517
|
+
Effect: "Allow",
|
|
518
|
+
Action: ["sqs:ReceiveMessage", "sqs:DeleteMessage"],
|
|
519
|
+
// A queue ARN has no resource type: not "...:queue/orders".
|
|
520
|
+
Resource: `arn:aws:sqs:${regionName}:${accountId}:orders`,
|
|
521
|
+
},
|
|
522
|
+
}),
|
|
523
|
+
}),
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const caller = { kind: "arn", arn: role.Role.Arn } as const;
|
|
527
|
+
|
|
528
|
+
const received = await sqs.receiveMessage(
|
|
529
|
+
new ReceiveMessageCommand({ QueueUrl }),
|
|
530
|
+
{ caller },
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
console.log(received.Messages?.[0]?.Body); // "order-1"
|
|
534
|
+
|
|
535
|
+
try {
|
|
536
|
+
await sqs.sendMessage(
|
|
537
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "order-2" }),
|
|
538
|
+
{ caller },
|
|
539
|
+
);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
console.log((error as Error).name); // "AccessDenied"
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Queue policies
|
|
546
|
+
|
|
547
|
+
A queue's `Policy` attribute is its resource policy, and simulated IAM evaluates it as one. It is
|
|
548
|
+
what admits a service principal such as `s3.amazonaws.com`, which owns no identity policies
|
|
549
|
+
anywhere. It is also half of what admits a principal from another account, which needs an identity
|
|
550
|
+
policy in its own account as well.
|
|
551
|
+
|
|
552
|
+
The policy is set with `CreateQueue` or `SetQueueAttributes` and read back with
|
|
553
|
+
`GetQueueAttributes`.
|
|
554
|
+
|
|
555
|
+
```typescript sim-sqs-queue-policy
|
|
556
|
+
/**
|
|
557
|
+
* A queue policy admitting S3 to send to a queue, for one Bucket only.
|
|
558
|
+
*/
|
|
559
|
+
|
|
560
|
+
import {
|
|
561
|
+
CreateQueueCommand,
|
|
562
|
+
SendMessageCommand,
|
|
563
|
+
SetQueueAttributesCommand,
|
|
564
|
+
} from "@aws-sdk/client-sqs";
|
|
565
|
+
|
|
566
|
+
import { SimAws } from "@kensio/yulin";
|
|
567
|
+
|
|
568
|
+
const simAws = new SimAws();
|
|
569
|
+
const sqs = simAws.sqs();
|
|
570
|
+
const queueArn = `arn:aws:sqs:${simAws.defaultRegionName}:${simAws.defaultAccountId}:orders`;
|
|
571
|
+
|
|
572
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
573
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
await sqs.setQueueAttributes(
|
|
577
|
+
new SetQueueAttributesCommand({
|
|
578
|
+
QueueUrl,
|
|
579
|
+
Attributes: {
|
|
580
|
+
Policy: JSON.stringify({
|
|
581
|
+
Version: "2012-10-17",
|
|
582
|
+
Statement: [
|
|
583
|
+
{
|
|
584
|
+
Effect: "Allow",
|
|
585
|
+
Principal: { Service: "s3.amazonaws.com" },
|
|
586
|
+
Action: "sqs:SendMessage",
|
|
587
|
+
Resource: queueArn,
|
|
588
|
+
Condition: { ArnLike: { "aws:SourceArn": "arn:aws:s3:::uploads" } },
|
|
589
|
+
},
|
|
590
|
+
],
|
|
591
|
+
}),
|
|
592
|
+
},
|
|
593
|
+
}),
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
// S3 has no identity policies anywhere, so the queue policy is the whole
|
|
597
|
+
// decision. What it is sending for goes in as aws:SourceArn.
|
|
598
|
+
const s3 = { kind: "service", service: "s3.amazonaws.com" } as const;
|
|
599
|
+
|
|
600
|
+
const sent = await sqs.sendMessage(
|
|
601
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "uploads/order-1.json" }),
|
|
602
|
+
{ caller: s3, sourceArn: "arn:aws:s3:::uploads" },
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
console.log(sent.MessageId !== undefined); // true
|
|
606
|
+
|
|
607
|
+
// A Bucket the condition does not cover is refused.
|
|
608
|
+
try {
|
|
609
|
+
await sqs.sendMessage(
|
|
610
|
+
new SendMessageCommand({ QueueUrl, MessageBody: "reports/order-1.json" }),
|
|
611
|
+
{ caller: s3, sourceArn: "arn:aws:s3:::reports" },
|
|
612
|
+
);
|
|
613
|
+
} catch (error) {
|
|
614
|
+
console.log((error as Error).name); // "AccessDenied"
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
`sourceArn` is what a request says it is being made on behalf of, and `sourceAccount` is the Account
|
|
619
|
+
owning that resource, supplied as `aws:SourceAccount`. A request that omits one leaves the key out
|
|
620
|
+
entirely, and a statement conditioned on it matches nothing.
|
|
621
|
+
|
|
622
|
+
A simulated S3 Bucket notifying a queue supplies both. The `ArnLike aws:SourceArn` condition CDK
|
|
623
|
+
writes and the `StringEquals aws:SourceAccount` guard AWS documents are each enough on their own.
|
|
624
|
+
See [Event notifications](https://yulinsim.dev/services/s3/#event-notifications) on the S3 page for the whole chain.
|
|
625
|
+
|
|
626
|
+
A caller from another account needs both sides to allow the request, as it does on real AWS. The
|
|
627
|
+
queue policy has to name the principal, and that principal's own account has to allow the action.
|
|
628
|
+
Either one on its own is a denial.
|
|
629
|
+
|
|
630
|
+
The policy is validated when it is set, by `CreateQueue` or `SetQueueAttributes`. A malformed
|
|
631
|
+
document fails there, before anything has been authorized against it. It has to be a JSON policy
|
|
632
|
+
document whose statements each carry an `Effect` of `Allow` or `Deny`, an `Action` or `NotAction`,
|
|
633
|
+
and a `Resource` or `NotResource`. Anything else fails with `InvalidAttributeValue`.
|
|
634
|
+
|
|
635
|
+
`GetQueueAttributes` reports `Policy` back as the string it was set with.
|
|
636
|
+
|
|
637
|
+
## Batches
|
|
638
|
+
|
|
639
|
+
`SendMessageBatch` and `DeleteMessageBatch` take up to ten entries. An entry that fails on its own is
|
|
640
|
+
reported in `Failed` while the rest of the batch goes through, as real SQS reports it. An empty batch,
|
|
641
|
+
more than ten entries, a malformed entry id or two entries sharing an id fail the whole request.
|
|
642
|
+
|
|
643
|
+
```typescript sim-sqs-send-message-batch
|
|
644
|
+
/**
|
|
645
|
+
* A batch send where one entry fails on its own.
|
|
646
|
+
*/
|
|
647
|
+
|
|
648
|
+
import {
|
|
649
|
+
CreateQueueCommand,
|
|
650
|
+
SendMessageBatchCommand,
|
|
651
|
+
} from "@aws-sdk/client-sqs";
|
|
652
|
+
|
|
653
|
+
import { SimAws } from "@kensio/yulin";
|
|
654
|
+
|
|
655
|
+
const simAws = new SimAws();
|
|
656
|
+
const sqs = simAws.sqs();
|
|
657
|
+
|
|
658
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
659
|
+
new CreateQueueCommand({
|
|
660
|
+
QueueName: "orders",
|
|
661
|
+
Attributes: { MaximumMessageSize: "1024" },
|
|
662
|
+
}),
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
const sent = await sqs.sendMessageBatch(
|
|
666
|
+
new SendMessageBatchCommand({
|
|
667
|
+
QueueUrl,
|
|
668
|
+
Entries: [
|
|
669
|
+
{ Id: "one", MessageBody: "order-1" },
|
|
670
|
+
{ Id: "two", MessageBody: "x".repeat(2048) },
|
|
671
|
+
],
|
|
672
|
+
}),
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
console.log(sent.Successful?.map((entry) => entry.Id)); // ["one"]
|
|
676
|
+
console.log(sent.Failed?.[0]?.Code); // "InvalidParameterValue"
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
## Deleting a queue
|
|
680
|
+
|
|
681
|
+
`DeleteQueue` removes the queue and everything on it. Real SQS holds a deleted queue's name for 60
|
|
682
|
+
seconds, and so does this. Advancing simulated time past the hold frees the name. A stack redeployed
|
|
683
|
+
in the same test depends on that.
|
|
684
|
+
|
|
685
|
+
```typescript sim-sqs-delete-queue
|
|
686
|
+
/**
|
|
687
|
+
* A deleted queue holding its name for a minute, as real SQS holds it.
|
|
688
|
+
*/
|
|
689
|
+
|
|
690
|
+
import { CreateQueueCommand, DeleteQueueCommand } from "@aws-sdk/client-sqs";
|
|
691
|
+
|
|
692
|
+
import { SimAws } from "@kensio/yulin";
|
|
693
|
+
import { SimSqsQueueDeletedRecently } from "@kensio/yulin/sqs";
|
|
694
|
+
|
|
695
|
+
const simAws = new SimAws();
|
|
696
|
+
const sqs = simAws.sqs();
|
|
697
|
+
|
|
698
|
+
const { QueueUrl } = await sqs.createQueue(
|
|
699
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
await sqs.deleteQueue(new DeleteQueueCommand({ QueueUrl }));
|
|
703
|
+
|
|
704
|
+
try {
|
|
705
|
+
await sqs.createQueue(new CreateQueueCommand({ QueueName: "orders" }));
|
|
706
|
+
} catch (error) {
|
|
707
|
+
console.log(error instanceof SimSqsQueueDeletedRecently); // true
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
await simAws.clock().advanceBy({ seconds: 61 });
|
|
711
|
+
|
|
712
|
+
const recreated = await sqs.createQueue(
|
|
713
|
+
new CreateQueueCommand({ QueueName: "orders" }),
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
console.log(recreated.QueueUrl === QueueUrl); // true
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
## Scoping
|
|
720
|
+
|
|
721
|
+
Queues belong to an account and a region, as they do on real AWS. A queue name is unique within one
|
|
722
|
+
account and region and nowhere wider. The same name can name two different queues in two regions.
|
|
723
|
+
|
|
724
|
+
```typescript sim-sqs-scoping
|
|
725
|
+
/**
|
|
726
|
+
* Simulated queues are scoped to an account and region.
|
|
727
|
+
*/
|
|
728
|
+
|
|
729
|
+
import {
|
|
730
|
+
CreateQueueCommand,
|
|
731
|
+
GetQueueUrlCommand,
|
|
732
|
+
SendMessageCommand,
|
|
733
|
+
} from "@aws-sdk/client-sqs";
|
|
734
|
+
|
|
735
|
+
import { SimAws } from "@kensio/yulin";
|
|
736
|
+
import { SimSqsQueueDoesNotExist } from "@kensio/yulin/sqs";
|
|
737
|
+
|
|
738
|
+
const simAws = new SimAws();
|
|
739
|
+
|
|
740
|
+
const { QueueUrl } = await simAws
|
|
741
|
+
.account("222222222222")
|
|
742
|
+
.region("eu-west-2")
|
|
743
|
+
.sqs()
|
|
744
|
+
.createQueue(new CreateQueueCommand({ QueueName: "orders" }));
|
|
745
|
+
|
|
746
|
+
try {
|
|
747
|
+
await simAws
|
|
748
|
+
.account("222222222222")
|
|
749
|
+
.region("us-east-1")
|
|
750
|
+
.sqs()
|
|
751
|
+
.getQueueUrl(new GetQueueUrlCommand({ QueueName: "orders" }));
|
|
752
|
+
} catch (error) {
|
|
753
|
+
console.log(error instanceof SimSqsQueueDoesNotExist); // true
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// A queue URL naming another Region reaches nothing either.
|
|
757
|
+
try {
|
|
758
|
+
await simAws
|
|
759
|
+
.account("222222222222")
|
|
760
|
+
.region("us-east-1")
|
|
761
|
+
.sqs()
|
|
762
|
+
.sendMessage(new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }));
|
|
763
|
+
} catch (error) {
|
|
764
|
+
console.log(error instanceof SimSqsQueueDoesNotExist); // true
|
|
765
|
+
}
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
## Inside a simulated Lambda handler
|
|
769
|
+
|
|
770
|
+
Function code requiring `@aws-sdk/client-sqs` is routed into the same simulated AWS environment, with
|
|
771
|
+
the function's execution role as the caller. A handler consuming a queue therefore has to be allowed
|
|
772
|
+
to, by that role's policy, the same as on real AWS.
|
|
773
|
+
|
|
774
|
+
```typescript sim-sqs-lambda-consumer
|
|
775
|
+
/**
|
|
776
|
+
* A simulated Lambda handler consuming a message from a simulated queue.
|
|
777
|
+
*/
|
|
778
|
+
|
|
779
|
+
import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
|
|
780
|
+
import { CreateFunctionCommand, InvokeCommand } from "@aws-sdk/client-lambda";
|
|
781
|
+
import { CreateQueueCommand, SendMessageCommand } from "@aws-sdk/client-sqs";
|
|
782
|
+
|
|
783
|
+
import { SimAws } from "@kensio/yulin";
|
|
784
|
+
import { makeLambdaCodeZip } from "@kensio/yulin/lambda";
|
|
785
|
+
|
|
786
|
+
const simAws = new SimAws();
|
|
787
|
+
const accountId = simAws.defaultAccountId;
|
|
788
|
+
const regionName = simAws.defaultRegionName;
|
|
789
|
+
|
|
790
|
+
const { QueueUrl } = await simAws
|
|
791
|
+
.sqs()
|
|
792
|
+
.createQueue(new CreateQueueCommand({ QueueName: "orders" }));
|
|
793
|
+
|
|
794
|
+
await simAws
|
|
795
|
+
.sqs()
|
|
796
|
+
.sendMessage(new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }));
|
|
797
|
+
|
|
798
|
+
const role = await simAws.iam().createRole(
|
|
799
|
+
new CreateRoleCommand({
|
|
800
|
+
RoleName: "OrderConsumerRole",
|
|
801
|
+
AssumeRolePolicyDocument: JSON.stringify({
|
|
802
|
+
Version: "2012-10-17",
|
|
803
|
+
Statement: {
|
|
804
|
+
Effect: "Allow",
|
|
805
|
+
Principal: { Service: "lambda.amazonaws.com" },
|
|
806
|
+
Action: "sts:AssumeRole",
|
|
807
|
+
},
|
|
808
|
+
}),
|
|
809
|
+
}),
|
|
810
|
+
);
|
|
811
|
+
|
|
812
|
+
await simAws.iam().putRolePolicy(
|
|
813
|
+
new PutRolePolicyCommand({
|
|
814
|
+
RoleName: "OrderConsumerRole",
|
|
815
|
+
PolicyName: "ConsumeOrders",
|
|
816
|
+
PolicyDocument: JSON.stringify({
|
|
817
|
+
Version: "2012-10-17",
|
|
818
|
+
Statement: {
|
|
819
|
+
Effect: "Allow",
|
|
820
|
+
Action: ["sqs:ReceiveMessage", "sqs:DeleteMessage"],
|
|
821
|
+
Resource: `arn:aws:sqs:${regionName}:${accountId}:orders`,
|
|
822
|
+
},
|
|
823
|
+
}),
|
|
824
|
+
}),
|
|
825
|
+
);
|
|
826
|
+
|
|
827
|
+
const handlerCode = [
|
|
828
|
+
'const { SQSClient, ReceiveMessageCommand, DeleteMessageCommand } = require("@aws-sdk/client-sqs");',
|
|
829
|
+
"exports.handler = async () => {",
|
|
830
|
+
" const client = new SQSClient({});",
|
|
831
|
+
" const received = await client.send(new ReceiveMessageCommand({",
|
|
832
|
+
" QueueUrl: process.env.QUEUE_URL,",
|
|
833
|
+
" }));",
|
|
834
|
+
" const message = received.Messages[0];",
|
|
835
|
+
" await client.send(new DeleteMessageCommand({",
|
|
836
|
+
" QueueUrl: process.env.QUEUE_URL,",
|
|
837
|
+
" ReceiptHandle: message.ReceiptHandle,",
|
|
838
|
+
" }));",
|
|
839
|
+
" return message.Body;",
|
|
840
|
+
"};",
|
|
841
|
+
].join("\n");
|
|
842
|
+
|
|
843
|
+
await simAws.lambda().createFunction(
|
|
844
|
+
new CreateFunctionCommand({
|
|
845
|
+
FunctionName: "order-consumer",
|
|
846
|
+
Role: role.Role.Arn,
|
|
847
|
+
Handler: "index.handler",
|
|
848
|
+
Code: { ZipFile: makeLambdaCodeZip({ "index.js": handlerCode }) },
|
|
849
|
+
Environment: { Variables: { QUEUE_URL: QueueUrl! } },
|
|
850
|
+
}),
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
await simAws.backgroundTasksComplete();
|
|
854
|
+
|
|
855
|
+
const invoked = await simAws
|
|
856
|
+
.lambda()
|
|
857
|
+
.invoke(new InvokeCommand({ FunctionName: "order-consumer" }));
|
|
858
|
+
|
|
859
|
+
console.log(Buffer.from(invoked.Payload ?? []).toString("utf8")); // "\"order-1\""
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
See [simulated Lambda](https://yulinsim.dev/services/lambda/ "Simulated Lambda docs") for how function code and execution roles
|
|
863
|
+
work. `SimSdk` interception works the same way. Intercepting `SQSClient` routes ordinary SDK code
|
|
864
|
+
into the simulation with nothing touching the network, covered under
|
|
865
|
+
[AWS SDK interception](https://yulinsim.dev/sdk/ "Simulated AWS SDK docs").
|
|
866
|
+
|
|
867
|
+
## Triggering a Lambda from a queue
|
|
868
|
+
|
|
869
|
+
A Lambda event source mapping delivers messages from a queue to a function without anything calling
|
|
870
|
+
`ReceiveMessage` itself. Messages sent to the queue arrive at the handler as an SQS event, in
|
|
871
|
+
batches of up to `BatchSize`.
|
|
872
|
+
|
|
873
|
+
Delivery runs on the simulation's background scheduler. A test waits for it with
|
|
874
|
+
`simAws.backgroundTasksComplete()`.
|
|
875
|
+
|
|
876
|
+
```typescript sim-sqs-lambda-event-source
|
|
877
|
+
/**
|
|
878
|
+
* A message sent to a queue reaching a Lambda through an event source mapping.
|
|
879
|
+
*/
|
|
880
|
+
|
|
881
|
+
import { CreateRoleCommand, PutRolePolicyCommand } from "@aws-sdk/client-iam";
|
|
882
|
+
import {
|
|
883
|
+
CreateEventSourceMappingCommand,
|
|
884
|
+
CreateFunctionCommand,
|
|
885
|
+
} from "@aws-sdk/client-lambda";
|
|
886
|
+
import {
|
|
887
|
+
CreateQueueCommand,
|
|
888
|
+
ReceiveMessageCommand,
|
|
889
|
+
SendMessageCommand,
|
|
890
|
+
} from "@aws-sdk/client-sqs";
|
|
891
|
+
|
|
892
|
+
import { SimAws } from "@kensio/yulin";
|
|
893
|
+
import {
|
|
894
|
+
makeLambdaZipFileInput,
|
|
895
|
+
type SimLambdaSqsEvent,
|
|
896
|
+
} from "@kensio/yulin/lambda";
|
|
897
|
+
|
|
898
|
+
const simAws = new SimAws();
|
|
899
|
+
const queueArn = `arn:aws:sqs:${simAws.defaultRegionName}:${simAws.defaultAccountId}:orders`;
|
|
900
|
+
|
|
901
|
+
const { QueueUrl } = await simAws
|
|
902
|
+
.sqs()
|
|
903
|
+
.createQueue(new CreateQueueCommand({ QueueName: "orders" }));
|
|
904
|
+
|
|
905
|
+
const role = await simAws.iam().createRole(
|
|
906
|
+
new CreateRoleCommand({
|
|
907
|
+
RoleName: "OrderConsumerRole",
|
|
908
|
+
AssumeRolePolicyDocument: JSON.stringify({
|
|
909
|
+
Version: "2012-10-17",
|
|
910
|
+
Statement: {
|
|
911
|
+
Effect: "Allow",
|
|
912
|
+
Principal: { Service: "lambda.amazonaws.com" },
|
|
913
|
+
Action: "sts:AssumeRole",
|
|
914
|
+
},
|
|
915
|
+
}),
|
|
916
|
+
}),
|
|
917
|
+
);
|
|
918
|
+
|
|
919
|
+
// Lambda polls the queue as the execution role, so the role has to allow it.
|
|
920
|
+
await simAws.iam().putRolePolicy(
|
|
921
|
+
new PutRolePolicyCommand({
|
|
922
|
+
RoleName: "OrderConsumerRole",
|
|
923
|
+
PolicyName: "ConsumeOrders",
|
|
924
|
+
PolicyDocument: JSON.stringify({
|
|
925
|
+
Version: "2012-10-17",
|
|
926
|
+
Statement: {
|
|
927
|
+
Effect: "Allow",
|
|
928
|
+
Action: [
|
|
929
|
+
"sqs:ReceiveMessage",
|
|
930
|
+
"sqs:DeleteMessage",
|
|
931
|
+
"sqs:GetQueueAttributes",
|
|
932
|
+
],
|
|
933
|
+
Resource: queueArn,
|
|
934
|
+
},
|
|
935
|
+
}),
|
|
936
|
+
}),
|
|
937
|
+
);
|
|
938
|
+
|
|
939
|
+
const consumed: string[] = [];
|
|
940
|
+
|
|
941
|
+
await simAws.lambda().createFunction(
|
|
942
|
+
new CreateFunctionCommand({
|
|
943
|
+
FunctionName: "order-consumer",
|
|
944
|
+
Role: role.Role.Arn,
|
|
945
|
+
Code: {
|
|
946
|
+
ZipFile: makeLambdaZipFileInput((event: SimLambdaSqsEvent) => {
|
|
947
|
+
for (const record of event.Records) {
|
|
948
|
+
consumed.push(record.body);
|
|
949
|
+
}
|
|
950
|
+
}),
|
|
951
|
+
},
|
|
952
|
+
}),
|
|
953
|
+
);
|
|
954
|
+
|
|
955
|
+
await simAws.lambda().createEventSourceMapping(
|
|
956
|
+
new CreateEventSourceMappingCommand({
|
|
957
|
+
EventSourceArn: queueArn,
|
|
958
|
+
FunctionName: "order-consumer",
|
|
959
|
+
}),
|
|
960
|
+
);
|
|
961
|
+
|
|
962
|
+
await simAws
|
|
963
|
+
.sqs()
|
|
964
|
+
.sendMessage(new SendMessageCommand({ QueueUrl, MessageBody: "order-1" }));
|
|
965
|
+
|
|
966
|
+
await simAws.backgroundTasksComplete();
|
|
967
|
+
|
|
968
|
+
console.log(consumed); // ["order-1"]
|
|
969
|
+
|
|
970
|
+
// The handler returned, so the message has been deleted from the queue.
|
|
971
|
+
const remaining = await simAws
|
|
972
|
+
.sqs()
|
|
973
|
+
.receiveMessage(new ReceiveMessageCommand({ QueueUrl }));
|
|
974
|
+
|
|
975
|
+
console.log(remaining.Messages); // undefined
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
A handler that throws leaves the whole batch on the queue instead. The messages stay hidden until
|
|
979
|
+
their visibility timeout lapses, come back after that, and eventually move to the dead-letter queue
|
|
980
|
+
if the queue has a `RedrivePolicy`. That is the path any other failing consumer takes, and advancing
|
|
981
|
+
the clock is what drives it:
|
|
982
|
+
|
|
983
|
+
```typescript
|
|
984
|
+
await simAws.clock().advanceBy({ seconds: 31 });
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
See [simulated Lambda](https://yulinsim.dev/services/lambda/#triggering-a-function-from-an-sqs-queue "Simulated Lambda event
|
|
988
|
+
source mapping docs") for the event shape, partial batch failures, and the
|
|
989
|
+
`AWS::Lambda::EventSourceMapping` template resource.
|
|
990
|
+
|
|
991
|
+
## Deploying a queue from CloudFormation
|
|
992
|
+
|
|
993
|
+
Simulated CloudFormation creates a queue from an `AWS::SQS::Queue` resource, in the stack's account
|
|
994
|
+
and region. The queue is created through `CreateQueue`. A template-created queue gets the same name
|
|
995
|
+
validation, the same attribute ranges and the same ARN and URL as one an SDK caller creates.
|
|
996
|
+
|
|
997
|
+
`Ref` on the resource gives the queue URL rather than its name or ARN, as it does on real AWS, and it
|
|
998
|
+
can be handed straight to `SendMessage`. `Fn::GetAtt … Arn`, `Fn::GetAtt … QueueName` and
|
|
999
|
+
`Fn::GetAtt … QueueUrl` give those.
|
|
1000
|
+
|
|
1001
|
+
```typescript sim-sqs-cloudformation-queue
|
|
1002
|
+
/**
|
|
1003
|
+
* Deploying a queue from a CloudFormation template and sending to it.
|
|
1004
|
+
*/
|
|
1005
|
+
|
|
1006
|
+
import { SendMessageCommand } from "@aws-sdk/client-sqs";
|
|
1007
|
+
|
|
1008
|
+
import { SimAws } from "@kensio/yulin";
|
|
1009
|
+
|
|
1010
|
+
const simAws = new SimAws();
|
|
1011
|
+
|
|
1012
|
+
const stack = await simAws.cloudFormation().deployTemplate({
|
|
1013
|
+
stackName: "orders-stack",
|
|
1014
|
+
template: {
|
|
1015
|
+
Resources: {
|
|
1016
|
+
OrdersQueue: {
|
|
1017
|
+
Type: "AWS::SQS::Queue",
|
|
1018
|
+
Properties: {
|
|
1019
|
+
QueueName: "orders",
|
|
1020
|
+
VisibilityTimeout: 120,
|
|
1021
|
+
MessageRetentionPeriod: 3600,
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
Outputs: {
|
|
1026
|
+
OrdersQueueUrl: {
|
|
1027
|
+
Value: { Ref: "OrdersQueue" },
|
|
1028
|
+
},
|
|
1029
|
+
OrdersQueueArn: {
|
|
1030
|
+
Value: { "Fn::GetAtt": ["OrdersQueue", "Arn"] },
|
|
1031
|
+
},
|
|
1032
|
+
},
|
|
1033
|
+
},
|
|
1034
|
+
});
|
|
1035
|
+
|
|
1036
|
+
await stack.waitForDeployComplete();
|
|
1037
|
+
|
|
1038
|
+
// Ref resolves to the queue URL, so it works as a SendMessage QueueUrl.
|
|
1039
|
+
const queueUrl = stack.output("OrdersQueueUrl");
|
|
1040
|
+
|
|
1041
|
+
await simAws
|
|
1042
|
+
.sqs()
|
|
1043
|
+
.sendMessage(
|
|
1044
|
+
new SendMessageCommand({ QueueUrl: queueUrl, MessageBody: "order-1" }),
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
console.log(stack.output("OrdersQueueArn"));
|
|
1048
|
+
// "arn:aws:sqs:us-east-1:888888888888:orders"
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
The properties applied to the queue are `VisibilityTimeout`, `DelaySeconds`,
|
|
1052
|
+
`MessageRetentionPeriod`, `MaximumMessageSize` and `ReceiveMessageWaitTimeSeconds`. Each is passed to
|
|
1053
|
+
`CreateQueue`, and a value outside the range real SQS accepts fails the resource.
|
|
1054
|
+
|
|
1055
|
+
A queue with no `QueueName` is named from the stack name, the logical ID and a tail derived from
|
|
1056
|
+
both. The queue above with its name left out would be `orders-stack-OrdersQueue-` and twelve more
|
|
1057
|
+
characters, where real CloudFormation ends the name in twelve random ones. The name is trimmed to
|
|
1058
|
+
the 80 characters a queue name allows, and [the CloudFormation docs](https://yulinsim.dev/services/cloudformation/#names-cloudformation-generates "Names CloudFormation generates")
|
|
1059
|
+
cover how the stack name and the logical ID share what is left.
|
|
1060
|
+
|
|
1061
|
+
`FifoQueue: true` fails the resource. Only standard queues are simulated, and a FIFO queue is named
|
|
1062
|
+
`<name>.fifo`, a name simulated SQS refuses to an SDK caller as well. There is no queue to create
|
|
1063
|
+
under the name the template gave it.
|
|
1064
|
+
|
|
1065
|
+
The properties this simulation has no behaviour for are a different case. The queue is created without
|
|
1066
|
+
them and each one is recorded in
|
|
1067
|
+
[`stack.ignoredProperties`](https://yulinsim.dev/services/cloudformation/#properties-a-resource-was-created-without).
|
|
1068
|
+
A stack full of queues still deploys. Those properties are `RedrivePolicy`, `RedriveAllowPolicy`,
|
|
1069
|
+
`KmsMasterKeyId`, `KmsDataKeyReusePeriodSeconds`, `SqsManagedSseEnabled`,
|
|
1070
|
+
`ContentBasedDeduplication`, `DeduplicationScope`, `FifoThroughputLimit` and `Tags`. A property
|
|
1071
|
+
outside the `AWS::SQS::Queue` schema is recorded the same way.
|
|
1072
|
+
|
|
1073
|
+
`AWS::SQS::QueuePolicy` deploys the policy it names onto each queue in its `Queues` list, through
|
|
1074
|
+
`SetQueueAttributes`. A policy declared in a template is therefore validated and enforced exactly as
|
|
1075
|
+
one set through the SDK, and a document SQS would refuse fails the resource. `Queues` carries queue
|
|
1076
|
+
URLs, and `Ref` on an `AWS::SQS::Queue` gives one.
|
|
1077
|
+
|
|
1078
|
+
```typescript
|
|
1079
|
+
{
|
|
1080
|
+
Type: "AWS::SQS::QueuePolicy",
|
|
1081
|
+
Properties: {
|
|
1082
|
+
Queues: [{ Ref: "OrdersQueue" }],
|
|
1083
|
+
PolicyDocument: {
|
|
1084
|
+
Version: "2012-10-17",
|
|
1085
|
+
Statement: [
|
|
1086
|
+
{
|
|
1087
|
+
Effect: "Allow",
|
|
1088
|
+
Principal: { Service: "s3.amazonaws.com" },
|
|
1089
|
+
Action: "sqs:SendMessage",
|
|
1090
|
+
Resource: { "Fn::GetAtt": ["OrdersQueue", "Arn"] },
|
|
1091
|
+
},
|
|
1092
|
+
],
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
1095
|
+
}
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
CDK works without hand-editing. An `sqs.Queue` with `grantSendMessages(fn)` synthesises a template
|
|
1099
|
+
that deploys here, with the queue URL reaching the function through its environment and the grant
|
|
1100
|
+
policy naming the queue by the ARN `Fn::GetAtt` gives. A grant to a service principal synthesises an
|
|
1101
|
+
`AWS::SQS::QueuePolicy` alongside it, which deploys too.
|
|
1102
|
+
|
|
1103
|
+
## Available functionality
|
|
1104
|
+
|
|
1105
|
+
Sim SQS currently supports:
|
|
1106
|
+
|
|
1107
|
+
- `CreateQueueCommand`, idempotent for a matching name and attributes, and `DeleteQueueCommand`
|
|
1108
|
+
- `GetQueueUrlCommand` and `ListQueuesCommand`, with a name prefix and paging
|
|
1109
|
+
- `GetQueueAttributesCommand`, `SetQueueAttributesCommand` and `PurgeQueueCommand`
|
|
1110
|
+
- `SendMessageCommand` and `SendMessageBatchCommand`, with per-message or per-queue delays
|
|
1111
|
+
- `ReceiveMessageCommand`, up to ten messages at a time, each under a fresh receipt handle
|
|
1112
|
+
- `DeleteMessageCommand`, `DeleteMessageBatchCommand` and `ChangeMessageVisibilityCommand`
|
|
1113
|
+
- Visibility timeouts, delays and message retention, all on the simulation's clock
|
|
1114
|
+
- `RedrivePolicy`, moving a message to its dead-letter queue once its receives run out
|
|
1115
|
+
- `MessageAttributes` round-tripping, with real `MD5OfMessageBody` and `MD5OfMessageAttributes` digests
|
|
1116
|
+
- The `SentTimestamp`, `ApproximateReceiveCount`, `ApproximateFirstReceiveTimestamp` and
|
|
1117
|
+
`DeadLetterQueueSourceArn` system attributes
|
|
1118
|
+
- Authorization of every operation by simulated IAM, against the real IAM action and queue ARN
|
|
1119
|
+
- The `Policy` attribute as the queue's resource policy, admitting another account's principal or a
|
|
1120
|
+
service principal, with `aws:SourceArn` and `aws:SourceAccount` conditions honoured
|
|
1121
|
+
- S3 event notifications sent to a queue, with the event document as the message body
|
|
1122
|
+
- Calls made from inside a simulated Lambda handler, authorized as the function's execution role
|
|
1123
|
+
- Lambda event source mappings, delivering messages to a simulated function and deleting the batches
|
|
1124
|
+
it handles
|
|
1125
|
+
- `AWS::SQS::Queue` and `AWS::SQS::QueuePolicy` in a CloudFormation or CDK template, with `Ref`
|
|
1126
|
+
giving the queue URL and `Fn::GetAtt` giving `Arn`, `QueueName` and `QueueUrl`
|
|
1127
|
+
|
|
1128
|
+
## Limitations
|
|
1129
|
+
|
|
1130
|
+
Current documented limitations:
|
|
1131
|
+
|
|
1132
|
+
- Standard queues only. A queue name ending in `.fifo` is refused, as are `MessageGroupId`,
|
|
1133
|
+
`MessageDeduplicationId` and `ReceiveRequestAttemptId`.
|
|
1134
|
+
- Ordering and duplicates are stricter here than AWS promises. Messages come back oldest first, and a
|
|
1135
|
+
message is handed out to one consumer at a time. Real standard queues promise no ordering at all
|
|
1136
|
+
and guarantee at-least-once delivery, so a copy of a message can arrive twice there and messages
|
|
1137
|
+
can arrive out of order. Redelivery after a visibility timeout lapses is simulated, since that
|
|
1138
|
+
follows from the timeout. A duplicate arriving on its own is left out.
|
|
1139
|
+
- Long polling answers at once. `WaitTimeSeconds` and `ReceiveMessageWaitTimeSeconds` are accepted
|
|
1140
|
+
and validated, and a receive returns immediately. The whole simulation runs in the calling process,
|
|
1141
|
+
where a wait could only ever time out.
|
|
1142
|
+
- `DeleteQueue` and `PurgeQueue` take effect immediately, where real SQS may take up to 60 seconds
|
|
1143
|
+
over either. The 60-second hold on a deleted queue's name is simulated, so recreating a queue
|
|
1144
|
+
straight after deleting it fails with `QueueDeletedRecently` until the clock moves on.
|
|
1145
|
+
- Dead-letter queues are simulated for standard queues only, and only the `RedrivePolicy` half of
|
|
1146
|
+
them. Setting `RedriveAllowPolicy` through the SQS API is refused, and on an `AWS::SQS::Queue` it
|
|
1147
|
+
is recorded and the queue created without it. A dead-letter queue cannot restrict which queues may
|
|
1148
|
+
redrive to it either way. `ListDeadLetterSourceQueues` and the `StartMessageMoveTask` family for
|
|
1149
|
+
draining a dead-letter queue back to its source are absent. A test moves a redriven message back by
|
|
1150
|
+
sending it again.
|
|
1151
|
+
- `ApproximateReceiveCount` starting again from one on a dead-letter queue is this simulation's
|
|
1152
|
+
reading of SQS, and AWS documents no answer either way. A receive count counts receives from one
|
|
1153
|
+
queue, and the moved message has not been received from the dead-letter queue yet. `SentTimestamp`
|
|
1154
|
+
being unchanged by the move is documented AWS behaviour, and is simulated as such.
|
|
1155
|
+
- The `RedrivePolicy` property on `AWS::SQS::Queue` is left out, and an SDK call is what configures a
|
|
1156
|
+
dead-letter queue. The queue is created without the property and the omission is recorded in
|
|
1157
|
+
`stack.ignoredProperties`.
|
|
1158
|
+
- A queue policy is set through the `Policy` attribute only. `AddPermission` and `RemovePermission`,
|
|
1159
|
+
shorthands for writing one statement of it, are absent.
|
|
1160
|
+
- `GetQueueAttributes` reports the `Policy` string that was set. Real SQS re-serialises the document
|
|
1161
|
+
and adds an `Id` and a `Sid` to it, so what comes back there differs from what went in.
|
|
1162
|
+
- A request naming a `QueueOwnerAWSAccountId` other than the scope's own account is refused. A queue
|
|
1163
|
+
policy admits another account's principal to a queue here, and leaves that account's own queues
|
|
1164
|
+
unreachable from this one.
|
|
1165
|
+
- Encryption is left out. `KmsMasterKeyId`, `KmsDataKeyReusePeriodSeconds` and
|
|
1166
|
+
`SqsManagedSseEnabled` are recorded on an `AWS::SQS::Queue` and applied to nothing, and message
|
|
1167
|
+
bodies are held in process memory as they were sent. Anything sharing the process can read them.
|
|
1168
|
+
- Tags are left out. `TagQueue`, `UntagQueue` and `ListQueueTags` are absent, and `CreateQueue`
|
|
1169
|
+
refuses a `tags` parameter rather than dropping it.
|
|
1170
|
+
- `SenderId` is left out, because a simulated caller has no user or role id to report it as.
|
|
1171
|
+
`AWSTraceHeader` is left out too, and `MessageSystemAttributes` on a send are refused. Asking for
|
|
1172
|
+
any of them is accepted, as real SQS accepts a request for an attribute a message has no value for,
|
|
1173
|
+
and they are absent from the response.
|
|
1174
|
+
- SQS condition keys are left out, and a policy relying on one matches nothing. Ordinary condition
|
|
1175
|
+
operators on values sim IAM does supply work as usual.
|
|
1176
|
+
- `ChangeMessageVisibilityBatch` and the batch size limit (`BatchRequestTooLong`) are absent.
|
|
1177
|
+
- A Lambda event source mapping polls one batch at a time. Real Lambda runs several pollers at once
|
|
1178
|
+
and scales them with the queue, and what that concurrency does to ordering is invisible here. See
|
|
1179
|
+
[simulated Lambda](https://yulinsim.dev/services/lambda/#triggering-a-function-from-an-sqs-queue "Simulated Lambda event
|
|
1180
|
+
source mapping docs") for the rest of the mapping limitations.
|
|
1181
|
+
- `AWS::SQS::Queue` and `AWS::SQS::QueuePolicy` are the SQS resource types CloudFormation creates.
|
|
1182
|
+
Any other is reported as unsupported and skipped. A queue attribute outside the range real SQS
|
|
1183
|
+
accepts fails the resource, and a property it has no behaviour for is recorded and the queue
|
|
1184
|
+
created without it.
|
|
1185
|
+
- SQS is not served as an HTTP API by `serveSimAws`.
|