From a0dba353eb2e1bcb4a00c147a0485f11ca451f9d Mon Sep 17 00:00:00 2001 From: exoego Date: Wed, 27 Sep 2023 18:45:59 +0900 Subject: [PATCH] Make log retention configurable --- .../04-standard-library/01-cloud/function.md | 16 + .../04-standard-library/01-cloud/on-deploy.md | 16 + .../04-standard-library/01-cloud/queue.md | 16 + .../04-standard-library/01-cloud/schedule.md | 16 + .../04-standard-library/01-cloud/service.md | 16 + .../04-standard-library/01-cloud/topic.md | 16 + .../incomplete_inflight_namespace.snap | 12 +- .../completions/namespace_middle_dot.snap | 12 +- .../variable_type_annotation_namespace.snap | 12 +- libs/wingsdk/src/cloud/function.ts | 7 + libs/wingsdk/src/target-awscdk/function.ts | 9 +- libs/wingsdk/src/target-tf-aws/function.ts | 14 +- .../__snapshots__/counter.test.ts.snap | 258 ++++++++++ .../__snapshots__/function.test.ts.snap | 307 ++++++++++++ .../__snapshots__/queue.test.ts.snap | 260 ++++++++++ .../test/target-awscdk/counter.test.ts | 2 +- .../test/target-awscdk/function.test.ts | 36 ++ libs/wingsdk/test/target-awscdk/queue.test.ts | 2 +- .../__snapshots__/function.test.ts.snap | 460 ++++++++++++++++++ .../test/target-tf-aws/function.test.ts | 44 ++ 20 files changed, 1505 insertions(+), 26 deletions(-) diff --git a/docs/docs/04-standard-library/01-cloud/function.md b/docs/docs/04-standard-library/01-cloud/function.md index 968671f5d38..5ca913888e7 100644 --- a/docs/docs/04-standard-library/01-cloud/function.md +++ b/docs/docs/04-standard-library/01-cloud/function.md @@ -220,6 +220,7 @@ let FunctionProps = cloud.FunctionProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | @@ -238,6 +239,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/docs/docs/04-standard-library/01-cloud/on-deploy.md b/docs/docs/04-standard-library/01-cloud/on-deploy.md index 4cbc2c42173..bf117b513cd 100644 --- a/docs/docs/04-standard-library/01-cloud/on-deploy.md +++ b/docs/docs/04-standard-library/01-cloud/on-deploy.md @@ -141,6 +141,7 @@ let OnDeployProps = cloud.OnDeployProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | | executeAfter | MutArray<constructs.Construct> | Execute this trigger only after these resources have been provisioned. | @@ -161,6 +162,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/docs/docs/04-standard-library/01-cloud/queue.md b/docs/docs/04-standard-library/01-cloud/queue.md index 30388ece49b..6a8b0a854b9 100644 --- a/docs/docs/04-standard-library/01-cloud/queue.md +++ b/docs/docs/04-standard-library/01-cloud/queue.md @@ -275,6 +275,7 @@ let QueueSetConsumerProps = cloud.QueueSetConsumerProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | | batchSize | num | The maximum number of messages to send to subscribers at once. | @@ -294,6 +295,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/docs/docs/04-standard-library/01-cloud/schedule.md b/docs/docs/04-standard-library/01-cloud/schedule.md index d4797df3977..94f4faf0f12 100644 --- a/docs/docs/04-standard-library/01-cloud/schedule.md +++ b/docs/docs/04-standard-library/01-cloud/schedule.md @@ -158,6 +158,7 @@ let ScheduleOnTickProps = cloud.ScheduleOnTickProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | @@ -176,6 +177,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/docs/docs/04-standard-library/01-cloud/service.md b/docs/docs/04-standard-library/01-cloud/service.md index 7e22d915d28..212f82f5c14 100644 --- a/docs/docs/04-standard-library/01-cloud/service.md +++ b/docs/docs/04-standard-library/01-cloud/service.md @@ -280,6 +280,7 @@ let ServiceOnStartProps = cloud.ServiceOnStartProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | @@ -298,6 +299,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/docs/docs/04-standard-library/01-cloud/topic.md b/docs/docs/04-standard-library/01-cloud/topic.md index 832f78e0427..aee02e86ed5 100644 --- a/docs/docs/04-standard-library/01-cloud/topic.md +++ b/docs/docs/04-standard-library/01-cloud/topic.md @@ -222,6 +222,7 @@ let TopicOnMessageProps = cloud.TopicOnMessageProps{ ... }; | **Name** | **Type** | **Description** | | --- | --- | --- | | env | MutMap<str> | Environment variables to pass to the function. | +| logRetentionDays | num | Specifies the number of days that function logs will be kept. | | memory | num | The amount of memory to allocate to the function, in MB. | | timeout | duration | The maximum amount of time the function can run. | @@ -240,6 +241,21 @@ Environment variables to pass to the function. --- +##### `logRetentionDays`Optional + +```wing +logRetentionDays: num; +``` + +- *Type:* num +- *Default:* 30 + +Specifies the number of days that function logs will be kept. + +Setting negative value means logs will not expire. + +--- + ##### `memory`Optional ```wing diff --git a/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap b/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap index 483708cf3f9..1fab9560840 100644 --- a/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap +++ b/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap @@ -191,7 +191,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." + value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `logRetentionDays?` — Specifies the number of days that function logs will be kept.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." sortText: hh|FunctionProps - label: GetSecretValueOptions kind: 22 @@ -203,7 +203,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|OnDeployProps - label: QueueProps kind: 22 @@ -215,13 +215,13 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|QueueSetConsumerProps - label: ScheduleOnTickProps kind: 22 documentation: kind: markdown - value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ScheduleOnTickProps - label: ScheduleProps kind: 22 @@ -239,7 +239,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ServiceOnStartProps - label: ServiceProps kind: 22 @@ -251,7 +251,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|TopicOnMessageProps - label: TopicProps kind: 22 diff --git a/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap b/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap index 483708cf3f9..1fab9560840 100644 --- a/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap +++ b/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap @@ -191,7 +191,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." + value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `logRetentionDays?` — Specifies the number of days that function logs will be kept.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." sortText: hh|FunctionProps - label: GetSecretValueOptions kind: 22 @@ -203,7 +203,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|OnDeployProps - label: QueueProps kind: 22 @@ -215,13 +215,13 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|QueueSetConsumerProps - label: ScheduleOnTickProps kind: 22 documentation: kind: markdown - value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ScheduleOnTickProps - label: ScheduleProps kind: 22 @@ -239,7 +239,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ServiceOnStartProps - label: ServiceProps kind: 22 @@ -251,7 +251,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|TopicOnMessageProps - label: TopicProps kind: 22 diff --git a/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap b/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap index 483708cf3f9..1fab9560840 100644 --- a/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap +++ b/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap @@ -191,7 +191,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." + value: "```wing\nstruct FunctionProps\n```\n---\nOptions for `Function`.\n### Fields\n- `env?` — Environment variables to pass to the function.\n- `logRetentionDays?` — Specifies the number of days that function logs will be kept.\n- `memory?` — The amount of memory to allocate to the function, in MB.\n- `timeout?` — The maximum amount of time the function can run." sortText: hh|FunctionProps - label: GetSecretValueOptions kind: 22 @@ -203,7 +203,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct OnDeployProps extends FunctionProps\n```\n---\nOptions for `OnDeploy`.\n### Fields\n- `env?` — Map?\n- `executeAfter?` — Execute this trigger only after these resources have been provisioned.\n- `executeBefore?` — Adds this trigger as a dependency on other constructs.\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|OnDeployProps - label: QueueProps kind: 22 @@ -215,13 +215,13 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct QueueSetConsumerProps extends FunctionProps\n```\n---\nOptions for Queue.setConsumer.\n### Fields\n- `batchSize?` — The maximum number of messages to send to subscribers at once.\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|QueueSetConsumerProps - label: ScheduleOnTickProps kind: 22 documentation: kind: markdown - value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ScheduleOnTickProps extends FunctionProps\n```\n---\nOptions for Schedule.onTick.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ScheduleOnTickProps - label: ScheduleProps kind: 22 @@ -239,7 +239,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct ServiceOnStartProps extends FunctionProps\n```\n---\nOptions for Service.onStart.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|ServiceOnStartProps - label: ServiceProps kind: 22 @@ -251,7 +251,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `memory?` — num?\n- `timeout?` — duration?" + value: "```wing\nstruct TopicOnMessageProps extends FunctionProps\n```\n---\nOptions for `Topic.onMessage`.\n### Fields\n- `env?` — Map?\n- `logRetentionDays?` — num?\n- `memory?` — num?\n- `timeout?` — duration?" sortText: hh|TopicOnMessageProps - label: TopicProps kind: 22 diff --git a/libs/wingsdk/src/cloud/function.ts b/libs/wingsdk/src/cloud/function.ts index ff9bc386e4b..6e53d0ff419 100644 --- a/libs/wingsdk/src/cloud/function.ts +++ b/libs/wingsdk/src/cloud/function.ts @@ -32,6 +32,13 @@ export interface FunctionProps { * @default 128 */ readonly memory?: number; + + /** + * Specifies the number of days that function logs will be kept. + * Setting negative value means logs will not expire. + * @default 30 + */ + readonly logRetentionDays?: number; } /** diff --git a/libs/wingsdk/src/target-awscdk/function.ts b/libs/wingsdk/src/target-awscdk/function.ts index 05cb2d7d012..93e89731d4a 100644 --- a/libs/wingsdk/src/target-awscdk/function.ts +++ b/libs/wingsdk/src/target-awscdk/function.ts @@ -36,6 +36,13 @@ export class Function extends cloud.Function implements IAwsFunction { // bundled code is guaranteed to be in a fresh directory const bundle = createBundle(this.entrypoint); + const logRetentionDays = + props.logRetentionDays === undefined + ? 30 + : props.logRetentionDays < 0 + ? undefined // Negative value means Infinite retention + : props.logRetentionDays; + this.function = new CdkFunction(this, "Default", { handler: "index.handler", code: Code.fromAsset(resolve(bundle.directory)), @@ -46,7 +53,7 @@ export class Function extends cloud.Function implements IAwsFunction { : Duration.minutes(1), memorySize: props.memory ? props.memory : undefined, architecture: Architecture.ARM_64, - logRetention: 30, + logRetention: logRetentionDays, }); this.arn = this.function.functionArn; diff --git a/libs/wingsdk/src/target-tf-aws/function.ts b/libs/wingsdk/src/target-tf-aws/function.ts index 190d9b50399..142a4fb5235 100644 --- a/libs/wingsdk/src/target-tf-aws/function.ts +++ b/libs/wingsdk/src/target-tf-aws/function.ts @@ -176,11 +176,6 @@ export class Function extends cloud.Function implements IAwsFunction { const name = ResourceNames.generateName(this, FUNCTION_NAME_OPTS); - new CloudwatchLogGroup(this, "CloudwatchLogGroup", { - name: `/aws/lambda/${name}`, - retentionInDays: 30, - }); - // validate memory size if (props.memory && (props.memory < 128 || props.memory > 10240)) { throw new Error( @@ -188,6 +183,15 @@ export class Function extends cloud.Function implements IAwsFunction { ); } + if (!props.logRetentionDays || props.logRetentionDays >= 0) { + new CloudwatchLogGroup(this, "CloudwatchLogGroup", { + name: `/aws/lambda/${name}`, + retentionInDays: props.logRetentionDays ?? 30, + }); + } else { + // Negative value means Infinite retention + } + // Create Lambda function this.function = new LambdaFunction(this, "Default", { functionName: name, diff --git a/libs/wingsdk/test/target-awscdk/__snapshots__/counter.test.ts.snap b/libs/wingsdk/test/target-awscdk/__snapshots__/counter.test.ts.snap index d69c117bf41..7615d2bf60f 100644 --- a/libs/wingsdk/test/target-awscdk/__snapshots__/counter.test.ts.snap +++ b/libs/wingsdk/test/target-awscdk/__snapshots__/counter.test.ts.snap @@ -426,6 +426,264 @@ my_counter: new (require(\\"[REDACTED]/wingsdk/src/shared-aws/counter.inflight\\ })" `; +exports[`function with a counter binding 2`] = ` +{ + "Outputs": { + "WingTestRunnerFunctionArns": { + "Value": "[]", + }, + }, + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "Counter44A08DAC": { + "DeletionPolicy": "Delete", + "Properties": { + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S", + }, + ], + "BillingMode": "PAY_PER_REQUEST", + "KeySchema": [ + { + "AttributeName": "id", + "KeyType": "HASH", + }, + ], + }, + "Type": "AWS::DynamoDB::Table", + "UpdateReplacePolicy": "Delete", + }, + "Function76856677": { + "DependsOn": [ + "FunctionServiceRoleDefaultPolicy2F49994A", + "FunctionServiceRole675BB04A", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Environment": { + "Variables": { + "DYNAMODB_TABLE_NAME_c7ebcb7a": { + "Ref": "Counter44A08DAC", + }, + }, + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "FunctionServiceRole675BB04A", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + "Timeout": 30, + }, + "Type": "AWS::Lambda::Function", + }, + "FunctionLogRetention5FDF6B4D": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "Function76856677", + }, + ], + ], + }, + "RetentionInDays": 30, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "FunctionServiceRole675BB04A": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "FunctionServiceRoleDefaultPolicy2F49994A": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:UpdateItem", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Counter44A08DAC", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "FunctionServiceRoleDefaultPolicy2F49994A", + "Roles": [ + { + "Ref": "FunctionServiceRole675BB04A", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + ], + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + }, + "Type": "AWS::Lambda::Function", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:PutRetentionPolicy", + "logs:DeleteRetentionPolicy", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + exports[`inc() policy statement 1`] = ` "new ((function(){ return class Handler { diff --git a/libs/wingsdk/test/target-awscdk/__snapshots__/function.test.ts.snap b/libs/wingsdk/test/target-awscdk/__snapshots__/function.test.ts.snap index e91a45635fd..2995adc4999 100644 --- a/libs/wingsdk/test/target-awscdk/__snapshots__/function.test.ts.snap +++ b/libs/wingsdk/test/target-awscdk/__snapshots__/function.test.ts.snap @@ -204,6 +204,210 @@ exports[`basic function 1`] = ` } `; +exports[`basic function with custom log retention 1`] = ` +{ + "Outputs": { + "WingTestRunnerFunctionArns": { + "Value": "[]", + }, + }, + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "Function76856677": { + "DependsOn": [ + "FunctionServiceRole675BB04A", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "FunctionServiceRole675BB04A", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + "Timeout": 30, + }, + "Type": "AWS::Lambda::Function", + }, + "FunctionLogRetention5FDF6B4D": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "Function76856677", + }, + ], + ], + }, + "RetentionInDays": 7, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "FunctionServiceRole675BB04A": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + ], + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + }, + "Type": "AWS::Lambda::Function", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:PutRetentionPolicy", + "logs:DeleteRetentionPolicy", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + exports[`basic function with environment variables 1`] = ` { "Outputs": { @@ -414,6 +618,109 @@ exports[`basic function with environment variables 1`] = ` } `; +exports[`basic function with infinite log retention 1`] = ` +{ + "Outputs": { + "WingTestRunnerFunctionArns": { + "Value": "[]", + }, + }, + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "Function76856677": { + "DependsOn": [ + "FunctionServiceRole675BB04A", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "FunctionServiceRole675BB04A", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + "Timeout": 30, + }, + "Type": "AWS::Lambda::Function", + }, + "FunctionServiceRole675BB04A": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + exports[`basic function with memory size specified 1`] = ` { "Outputs": { diff --git a/libs/wingsdk/test/target-awscdk/__snapshots__/queue.test.ts.snap b/libs/wingsdk/test/target-awscdk/__snapshots__/queue.test.ts.snap index 3cf605dd4f1..e6315946431 100644 --- a/libs/wingsdk/test/target-awscdk/__snapshots__/queue.test.ts.snap +++ b/libs/wingsdk/test/target-awscdk/__snapshots__/queue.test.ts.snap @@ -53,6 +53,266 @@ exports[`default queue behavior 1`] = ` exports[`queue with a consumer function 1`] = `"new (require(\\"[REDACTED]/wingsdk/src/shared-aws/function.inflight\\")).FunctionClient(process.env[\\"FUNCTION_NAME_b3dcdeaa\\"], \\"my-project/Default/Queue-SetConsumer-c185c7e3\\")"`; +exports[`queue with a consumer function 2`] = ` +{ + "Outputs": { + "WingTestRunnerFunctionArns": { + "Value": "[]", + }, + }, + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + ], + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + }, + "Type": "AWS::Lambda::Function", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:PutRetentionPolicy", + "logs:DeleteRetentionPolicy", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "Queue4A7E3555": { + "DeletionPolicy": "Delete", + "Properties": { + "VisibilityTimeout": 30, + }, + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + }, + "QueueSetConsumerc185c7e3BBF127FC": { + "DependsOn": [ + "QueueSetConsumerc185c7e3ServiceRoleDefaultPolicy707C955E", + "QueueSetConsumerc185c7e3ServiceRole98E9022D", + ], + "Properties": { + "Architectures": [ + "arm64", + ], + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", + }, + "S3Key": "", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "QueueSetConsumerc185c7e3ServiceRole98E9022D", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + "Timeout": 30, + }, + "Type": "AWS::Lambda::Function", + }, + "QueueSetConsumerc185c7e3LogRetention988E9F20": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "QueueSetConsumerc185c7e3BBF127FC", + }, + ], + ], + }, + "RetentionInDays": 30, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "QueueSetConsumerc185c7e3ServiceRole98E9022D": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "QueueSetConsumerc185c7e3ServiceRoleDefaultPolicy707C955E": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:ChangeMessageVisibility", + "sqs:GetQueueUrl", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn", + ], + }, + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "QueueSetConsumerc185c7e3ServiceRoleDefaultPolicy707C955E", + "Roles": [ + { + "Ref": "QueueSetConsumerc185c7e3ServiceRole98E9022D", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "QueueSetConsumerc185c7e3SqsEventSourcemyprojectQueue97F83A7BF9F5BDF6": { + "Properties": { + "BatchSize": 1, + "EventSourceArn": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn", + ], + }, + "FunctionName": { + "Ref": "QueueSetConsumerc185c7e3BBF127FC", + }, + }, + "Type": "AWS::Lambda::EventSourceMapping", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + exports[`queue with custom retention 1`] = ` { "Outputs": { diff --git a/libs/wingsdk/test/target-awscdk/counter.test.ts b/libs/wingsdk/test/target-awscdk/counter.test.ts index d6b1d9efda9..5d2526a367e 100644 --- a/libs/wingsdk/test/target-awscdk/counter.test.ts +++ b/libs/wingsdk/test/target-awscdk/counter.test.ts @@ -70,7 +70,7 @@ test("function with a counter binding", () => { const template = Template.fromJSON(JSON.parse(output)); template.resourceCountIs("AWS::DynamoDB::Table", 1); template.resourceCountIs("AWS::IAM::Role", 2); - template.resourceCountIs("AWS::IAM::Policy", 1); + template.resourceCountIs("AWS::IAM::Policy", 2); template.resourceCountIs("AWS::Lambda::Function", 2); expect(awscdkSanitize(template)).toMatchSnapshot(); }); diff --git a/libs/wingsdk/test/target-awscdk/function.test.ts b/libs/wingsdk/test/target-awscdk/function.test.ts index b9456dbd38b..893a4bab0ff 100644 --- a/libs/wingsdk/test/target-awscdk/function.test.ts +++ b/libs/wingsdk/test/target-awscdk/function.test.ts @@ -30,6 +30,10 @@ test("basic function", () => { Timeout: 60, }) ); + expect( + Object.keys(template.findResources("Custom::LogRetention")).length, + "should have LogRetention" + ).toEqual(1); expect(awscdkSanitize(template)).toMatchSnapshot(); }); @@ -105,3 +109,35 @@ test("basic function with memory size specified", () => { ); expect(awscdkSanitize(template)).toMatchSnapshot(); }); + +test("basic function with custom log retention", () => { + // GIVEN + const app = new awscdk.App({ outdir: mkdtemp(), ...CDK_APP_OPTS }); + const inflight = Testing.makeHandler(app, "Handler", INFLIGHT_CODE); + Function._newFunction(app, "Function", inflight, { logRetentionDays: 7 }); + const output = app.synth(); + + // THEN + const template = Template.fromJSON(JSON.parse(output)); + expect( + Object.keys(template.findResources("Custom::LogRetention")).length, + "should have LogRetention" + ).toEqual(1); + expect(awscdkSanitize(template)).toMatchSnapshot(); +}); + +test("basic function with infinite log retention", () => { + // GIVEN + const app = new awscdk.App({ outdir: mkdtemp(), ...CDK_APP_OPTS }); + const inflight = Testing.makeHandler(app, "Handler", INFLIGHT_CODE); + Function._newFunction(app, "Function", inflight, { logRetentionDays: -1 }); + const output = app.synth(); + + // THEN + const template = Template.fromJSON(JSON.parse(output)); + expect( + Object.keys(template.findResources("Custom::LogRetention")).length, + "should NOT have LogRetention" + ).toEqual(0); + expect(awscdkSanitize(template)).toMatchSnapshot(); +}); diff --git a/libs/wingsdk/test/target-awscdk/queue.test.ts b/libs/wingsdk/test/target-awscdk/queue.test.ts index 41fca46e50e..378e4067dd3 100644 --- a/libs/wingsdk/test/target-awscdk/queue.test.ts +++ b/libs/wingsdk/test/target-awscdk/queue.test.ts @@ -72,7 +72,7 @@ async handle(event) { template.resourceCountIs("AWS::SQS::Queue", 1); template.resourceCountIs("AWS::Lambda::Function", 2); template.resourceCountIs("AWS::IAM::Role", 2); - template.resourceCountIs("AWS::IAM::Policy", 1); + template.resourceCountIs("AWS::IAM::Policy", 2); template.resourceCountIs("AWS::Lambda::EventSourceMapping", 1); expect(awscdkSanitize(template)).toMatchSnapshot(); }); diff --git a/libs/wingsdk/test/target-tf-aws/__snapshots__/function.test.ts.snap b/libs/wingsdk/test/target-tf-aws/__snapshots__/function.test.ts.snap index a25de17c946..3aa0e412c6c 100644 --- a/libs/wingsdk/test/target-tf-aws/__snapshots__/function.test.ts.snap +++ b/libs/wingsdk/test/target-tf-aws/__snapshots__/function.test.ts.snap @@ -237,6 +237,243 @@ exports[`basic function 2`] = ` } `; +exports[`basic function with custom log retention 1`] = ` +{ + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]", + }, + }, + "resource": { + "aws_cloudwatch_log_group": { + "Function_CloudwatchLogGroup_ABDCF4C4": { + "name": "/aws/lambda/Function-c852aba6", + "retention_in_days": 7, + }, + }, + "aws_iam_role": { + "Function_IamRole_678BE84C": { + "assume_role_policy": "{\\"Version\\":\\"2012-10-17\\",\\"Statement\\":[{\\"Action\\":\\"sts:AssumeRole\\",\\"Principal\\":{\\"Service\\":\\"lambda.amazonaws.com\\"},\\"Effect\\":\\"Allow\\"}]}", + }, + }, + "aws_iam_role_policy": { + "Function_IamRolePolicy_E3B26607": { + "policy": "{\\"Version\\":\\"2012-10-17\\",\\"Statement\\":[{\\"Effect\\":\\"Allow\\",\\"Action\\":\\"none:null\\",\\"Resource\\":\\"*\\"}]}", + "role": "\${aws_iam_role.Function_IamRole_678BE84C.name}", + }, + }, + "aws_iam_role_policy_attachment": { + "Function_IamRolePolicyAttachment_CACE1358": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "\${aws_iam_role.Function_IamRole_678BE84C.name}", + }, + }, + "aws_lambda_function": { + "Function": { + "architectures": [ + "arm64", + ], + "environment": { + "variables": { + "WING_FUNCTION_NAME": "Function-c852aba6", + }, + }, + "function_name": "Function-c852aba6", + "handler": "index.handler", + "publish": true, + "role": "\${aws_iam_role.Function_IamRole_678BE84C.arn}", + "runtime": "nodejs18.x", + "s3_bucket": "\${aws_s3_bucket.Code.bucket}", + "s3_key": "\${aws_s3_object.Function_S3Object_C62A0C2D.key}", + "timeout": 30, + "vpc_config": { + "security_group_ids": [], + "subnet_ids": [], + }, + }, + }, + "aws_s3_bucket": { + "Code": { + "bucket_prefix": "code-c84a50b1-", + }, + }, + "aws_s3_object": { + "Function_S3Object_C62A0C2D": { + "bucket": "\${aws_s3_bucket.Code.bucket}", + "key": "", + "source": "", + }, + }, + }, +} +`; + +exports[`basic function with custom log retention 2`] = ` +{ + "tree": { + "children": { + "root": { + "children": { + "Default": { + "children": { + "Code": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "Code", + "path": "root/Default/Code", + }, + "Function": { + "children": { + "Asset": { + "constructInfo": { + "fqn": "cdktf.TerraformAsset", + "version": "0.17.0", + }, + "id": "Asset", + "path": "root/Default/Function/Asset", + }, + "CloudwatchLogGroup": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "CloudwatchLogGroup", + "path": "root/Default/Function/CloudwatchLogGroup", + }, + "Default": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "Default", + "path": "root/Default/Function/Default", + }, + "IamRole": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRole", + "path": "root/Default/Function/IamRole", + }, + "IamRolePolicy": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRolePolicy", + "path": "root/Default/Function/IamRolePolicy", + }, + "IamRolePolicyAttachment": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRolePolicyAttachment", + "path": "root/Default/Function/IamRolePolicyAttachment", + }, + "S3Object": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "S3Object", + "path": "root/Default/Function/S3Object", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "A cloud function (FaaS)", + "title": "Function", + }, + "id": "Function", + "path": "root/Default/Function", + }, + "Handler": { + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "An inflight resource", + "hidden": true, + "title": "Inflight", + }, + "id": "Handler", + "path": "root/Default/Handler", + }, + "aws": { + "constructInfo": { + "fqn": "cdktf.TerraformProvider", + "version": "0.17.0", + }, + "id": "aws", + "path": "root/Default/aws", + }, + "cloud.TestRunner": { + "children": { + "TestFunctionArns": { + "constructInfo": { + "fqn": "cdktf.TerraformOutput", + "version": "0.17.0", + }, + "id": "TestFunctionArns", + "path": "root/Default/cloud.TestRunner/TestFunctionArns", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "A suite of APIs for running tests and collecting results.", + "hidden": true, + "title": "TestRunner", + }, + "id": "cloud.TestRunner", + "path": "root/Default/cloud.TestRunner", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "id": "Default", + "path": "root/Default", + }, + "backend": { + "constructInfo": { + "fqn": "cdktf.LocalBackend", + "version": "0.17.0", + }, + "id": "backend", + "path": "root/backend", + }, + }, + "constructInfo": { + "fqn": "cdktf.TerraformStack", + "version": "0.17.0", + }, + "id": "root", + "path": "root", + }, + }, + "constructInfo": { + "fqn": "cdktf.App", + "version": "0.17.0", + }, + "id": "App", + "path": "", + }, + "version": "tree-0.1", +} +`; + exports[`basic function with environment variables 1`] = ` { "output": { @@ -476,6 +713,229 @@ exports[`basic function with environment variables 2`] = ` } `; +exports[`basic function with infinite log retention 1`] = ` +{ + "output": { + "WING_TEST_RUNNER_FUNCTION_ARNS": { + "value": "[]", + }, + }, + "resource": { + "aws_iam_role": { + "Function_IamRole_678BE84C": { + "assume_role_policy": "{\\"Version\\":\\"2012-10-17\\",\\"Statement\\":[{\\"Action\\":\\"sts:AssumeRole\\",\\"Principal\\":{\\"Service\\":\\"lambda.amazonaws.com\\"},\\"Effect\\":\\"Allow\\"}]}", + }, + }, + "aws_iam_role_policy": { + "Function_IamRolePolicy_E3B26607": { + "policy": "{\\"Version\\":\\"2012-10-17\\",\\"Statement\\":[{\\"Effect\\":\\"Allow\\",\\"Action\\":\\"none:null\\",\\"Resource\\":\\"*\\"}]}", + "role": "\${aws_iam_role.Function_IamRole_678BE84C.name}", + }, + }, + "aws_iam_role_policy_attachment": { + "Function_IamRolePolicyAttachment_CACE1358": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "\${aws_iam_role.Function_IamRole_678BE84C.name}", + }, + }, + "aws_lambda_function": { + "Function": { + "architectures": [ + "arm64", + ], + "environment": { + "variables": { + "WING_FUNCTION_NAME": "Function-c852aba6", + }, + }, + "function_name": "Function-c852aba6", + "handler": "index.handler", + "publish": true, + "role": "\${aws_iam_role.Function_IamRole_678BE84C.arn}", + "runtime": "nodejs18.x", + "s3_bucket": "\${aws_s3_bucket.Code.bucket}", + "s3_key": "\${aws_s3_object.Function_S3Object_C62A0C2D.key}", + "timeout": 30, + "vpc_config": { + "security_group_ids": [], + "subnet_ids": [], + }, + }, + }, + "aws_s3_bucket": { + "Code": { + "bucket_prefix": "code-c84a50b1-", + }, + }, + "aws_s3_object": { + "Function_S3Object_C62A0C2D": { + "bucket": "\${aws_s3_bucket.Code.bucket}", + "key": "", + "source": "", + }, + }, + }, +} +`; + +exports[`basic function with infinite log retention 2`] = ` +{ + "tree": { + "children": { + "root": { + "children": { + "Default": { + "children": { + "Code": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "Code", + "path": "root/Default/Code", + }, + "Function": { + "children": { + "Asset": { + "constructInfo": { + "fqn": "cdktf.TerraformAsset", + "version": "0.17.0", + }, + "id": "Asset", + "path": "root/Default/Function/Asset", + }, + "Default": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "Default", + "path": "root/Default/Function/Default", + }, + "IamRole": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRole", + "path": "root/Default/Function/IamRole", + }, + "IamRolePolicy": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRolePolicy", + "path": "root/Default/Function/IamRolePolicy", + }, + "IamRolePolicyAttachment": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "IamRolePolicyAttachment", + "path": "root/Default/Function/IamRolePolicyAttachment", + }, + "S3Object": { + "constructInfo": { + "fqn": "cdktf.TerraformResource", + "version": "0.17.0", + }, + "id": "S3Object", + "path": "root/Default/Function/S3Object", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "A cloud function (FaaS)", + "title": "Function", + }, + "id": "Function", + "path": "root/Default/Function", + }, + "Handler": { + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "An inflight resource", + "hidden": true, + "title": "Inflight", + }, + "id": "Handler", + "path": "root/Default/Handler", + }, + "aws": { + "constructInfo": { + "fqn": "cdktf.TerraformProvider", + "version": "0.17.0", + }, + "id": "aws", + "path": "root/Default/aws", + }, + "cloud.TestRunner": { + "children": { + "TestFunctionArns": { + "constructInfo": { + "fqn": "cdktf.TerraformOutput", + "version": "0.17.0", + }, + "id": "TestFunctionArns", + "path": "root/Default/cloud.TestRunner/TestFunctionArns", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "display": { + "description": "A suite of APIs for running tests and collecting results.", + "hidden": true, + "title": "TestRunner", + }, + "id": "cloud.TestRunner", + "path": "root/Default/cloud.TestRunner", + }, + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70", + }, + "id": "Default", + "path": "root/Default", + }, + "backend": { + "constructInfo": { + "fqn": "cdktf.LocalBackend", + "version": "0.17.0", + }, + "id": "backend", + "path": "root/backend", + }, + }, + "constructInfo": { + "fqn": "cdktf.TerraformStack", + "version": "0.17.0", + }, + "id": "root", + "path": "root", + }, + }, + "constructInfo": { + "fqn": "cdktf.App", + "version": "0.17.0", + }, + "id": "App", + "path": "", + }, + "version": "tree-0.1", +} +`; + exports[`basic function with memory size specified 1`] = ` { "output": { diff --git a/libs/wingsdk/test/target-tf-aws/function.test.ts b/libs/wingsdk/test/target-tf-aws/function.test.ts index 7b3e531c620..cebbd165b1b 100644 --- a/libs/wingsdk/test/target-tf-aws/function.test.ts +++ b/libs/wingsdk/test/target-tf-aws/function.test.ts @@ -23,6 +23,15 @@ test("basic function", () => { "aws_s3_bucket", // S3 bucket for code "aws_s3_object", // S3 object for code ]); + expect( + cdktf.Testing.toHaveResourceWithProperties( + output, + "aws_cloudwatch_log_group", + { + retention_in_days: 30, + } + ) + ).toEqual(true); expect(tfSanitize(output)).toMatchSnapshot(); expect(treeJsonOf(app.outdir)).toMatchSnapshot(); }); @@ -120,6 +129,41 @@ test("basic function with memory size specified", () => { expect(treeJsonOf(app.outdir)).toMatchSnapshot(); }); +test("basic function with custom log retention", () => { + const app = new tfaws.App({ outdir: mkdtemp() }); + const inflight = Testing.makeHandler(app, "Handler", INFLIGHT_CODE); + Function._newFunction(app, "Function", inflight, { logRetentionDays: 7 }); + const output = app.synth(); + + expect( + cdktf.Testing.toHaveResourceWithProperties( + output, + "aws_cloudwatch_log_group", + { + retention_in_days: 7, + } + ) + ).toEqual(true); + expect(tfSanitize(output)).toMatchSnapshot(); + expect(treeJsonOf(app.outdir)).toMatchSnapshot(); +}); + +test("basic function with infinite log retention", () => { + const app = new tfaws.App({ outdir: mkdtemp() }); + const inflight = Testing.makeHandler(app, "Handler", INFLIGHT_CODE); + Function._newFunction(app, "Function", inflight, { logRetentionDays: -1 }); + const output = app.synth(); + + expect( + cdktf.Testing.toHaveResourceWithProperties( + output, + "aws_cloudwatch_log_group" + ) + ).toEqual(false); + expect(tfSanitize(output)).toMatchSnapshot(); + expect(treeJsonOf(app.outdir)).toMatchSnapshot(); +}); + test("asset path is stripped of spaces", () => { // GIVEN const some_name = "I have a space in my name";