From 83487a6d2f025926dbc3a89aa46e8f3291cb02f0 Mon Sep 17 00:00:00 2001 From: nozaq Date: Mon, 10 Jan 2022 10:38:58 +0900 Subject: [PATCH] refactor: add tflint checks (#15) * refactor: add tflint checks * style: apply consistent comment style --- .github/workflows/main.yml | 16 +++--- .pre-commit-config.yaml | 8 ++- .terraform-docs.yml | 16 ++++++ .tflint.hcl | 53 ++++++++++++++++++ README.md | 84 ++++++++++++----------------- examples/simple-nodejs/outputs.tf | 1 + examples/simple-nodejs/variables.tf | 1 + examples/simple-py/outputs.tf | 0 examples/simple-py/variables.tf | 1 + main.tf | 27 +++++++++- variables.tf | 26 +++++---- 11 files changed, 165 insertions(+), 68 deletions(-) create mode 100644 .terraform-docs.yml create mode 100644 .tflint.hcl create mode 100644 examples/simple-nodejs/outputs.tf create mode 100644 examples/simple-py/outputs.tf diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index db46963..e70040e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,16 +7,20 @@ on: env: TF_ACTIONS_VERSION: latest jobs: - check-format: - name: Check format + pre-commit-checks: + name: Pre-commit checks runs-on: ubuntu-latest steps: - - uses: hashicorp/setup-terraform@v1 - name: Checkout uses: actions/checkout@v2 - - name: "Terraform Format" - run: terraform fmt -check -recursive - + - name: Terraform min/max versions + id: minMax + uses: clowdhaus/terraform-min-max@v1.0.4 + - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.4.1 + with: + terraform-version: ${{ steps.minMax.outputs.maxVersion }} + terraform-docs-version: v0.16.0 validate-examples: name: Validate examples runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5faa956..4be71ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,12 @@ repos: - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.51.0 + rev: v1.62.3 hooks: - id: terraform_fmt - id: terraform_docs + args: + - --args=--config=.terraform-docs.yml + - id: terraform_tflint + exclude: "test/" + args: + - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl diff --git a/.terraform-docs.yml b/.terraform-docs.yml new file mode 100644 index 0000000..8918a21 --- /dev/null +++ b/.terraform-docs.yml @@ -0,0 +1,16 @@ +formatter: "markdown table" + +sections: + show: + - requirements + - providers + - inputs + - outputs + +sort: + enabled: true + by: name + +settings: + default: false + lockfile: false diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 0000000..714b601 --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,53 @@ +config { + module = false + force = false + disabled_by_default = false +} + +rule "terraform_deprecated_interpolation" { + enabled = true +} + +rule "terraform_deprecated_index" { + enabled = true +} + +rule "terraform_unused_declarations" { + enabled = true +} + +rule "terraform_comment_syntax" { + enabled = true +} + +rule "terraform_documented_outputs" { + enabled = true +} + +rule "terraform_documented_variables" { + enabled = true +} + +rule "terraform_typed_variables" { + enabled = true +} + +rule "terraform_module_pinned_source" { + enabled = true +} + +rule "terraform_required_version" { + enabled = true +} + +rule "terraform_required_providers" { + enabled = true +} + +rule "terraform_standard_module_structure" { + enabled = true +} + +rule "terraform_workspace_remote" { + enabled = true +} diff --git a/README.md b/README.md index 51ecddd..d849555 100644 --- a/README.md +++ b/README.md @@ -48,63 +48,49 @@ Check [examples](./examples) for non-python examples. ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.15.0 | +| [archive](#requirement\_archive) | >= 2.2.0 | +| [aws](#requirement\_aws) | >= 3.50.0 | +| [null](#requirement\_null) | >= 3.1.0 | ## Providers | Name | Version | |------|---------| -| [archive](#provider\_archive) | n/a | -| [aws](#provider\_aws) | n/a | -| [null](#provider\_null) | n/a | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.basic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [null_resource.build](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | -| [archive_file.source](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [aws_iam_policy_document.assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [archive](#provider\_archive) | >= 2.2.0 | +| [aws](#provider\_aws) | >= 3.50.0 | +| [null](#provider\_null) | >= 3.1.0 | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [allowed\_services](#input\_allowed\_services) | A list of AWS Services that are allowed to access this lambda. | `list(string)` |
[
"lambda.amazonaws.com"
]
| no | -| [build\_command](#input\_build\_command) | This is the build command to execute. It can be provided as a relative path to the current working directory or as an absolute path. It is evaluated in a shell, and can use environment variables or Terraform variables. | `string` | `""` | no | -| [build\_triggers](#input\_build\_triggers) | A map of values which should cause the build command to re-run. Values are meant to be interpolated references to variables or attributes of other resources. | `list` | `[]` | no | -| [dead\_letter\_config](#input\_dead\_letter\_config) | Nested block to configure the function's dead letter queue. |
object({
target_arn = string
})
| `null` | no | -| [description](#input\_description) | Description of what your Lambda Function does. | `string` | `""` | no | -| [environment](#input\_environment) | A map that defines environment variables for the Lambda function. |
object({
variables = map(string)
})
| `null` | no | -| [exclude\_files](#input\_exclude\_files) | A list of directories or folders to ignore, e.g.
exclude\_files = ["test", "src/**/*.ts"] | `list(string)` | `[]` | no | -| [function\_name](#input\_function\_name) | A unique name for your Lambda Function. | `string` | n/a | yes | -| [handler](#input\_handler) | The function entrypoint in your code. | `string` | n/a | yes | -| [iam\_role\_name\_prefix](#input\_iam\_role\_name\_prefix) | The prefix string for the name of IAM role for the lambda function. | `string` | `""` | no | -| [kms\_key\_arn](#input\_kms\_key\_arn) | The ARN for the KMS encryption key. | `string` | `null` | no | -| [kms\_key\_id](#input\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data. | `string` | `null` | no | -| [layers](#input\_layers) | List of Lambda Layer Version ARNs (maximum of 5) to attach to your Lambda Function. | `list(string)` | `[]` | no | -| [memory\_size](#input\_memory\_size) | Amount of memory in MB your Lambda Function can use at runtime. | `number` | `128` | no | -| [output\_path](#input\_output\_path) | A path to which the source directory is archived before uploading to AWS. | `string` | n/a | yes | -| [policy\_arns](#input\_policy\_arns) | A list of IAM policy ARNs attached to the lambda function. | `list(string)` | `[]` | no | -| [publish](#input\_publish) | Whether to publish creation/change as new Lambda Function Version. | `string` | `false` | no | -| [reserved\_concurrent\_executions](#input\_reserved\_concurrent\_executions) | The amount of reserved concurrent executions for this lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `string` | `-1` | no | -| [retention\_in\_days](#input\_retention\_in\_days) | Specifies the number of days you want to retain log events in the specified log group. | `number` | `null` | no | -| [runtime](#input\_runtime) | The identifier of the function's runtime. | `string` | n/a | yes | -| [source\_dir](#input\_source\_dir) | A path to the directory which contains source files. | `string` | n/a | yes | -| [tags](#input\_tags) | A mapping of tags to assign to resources. | `map` |
{
"Terraform": "true"
}
| no | -| [timeout](#input\_timeout) | The maximum number of seconds the lambda function to run until timeout. | `number` | `3` | no | -| [tracing\_config](#input\_tracing\_config) | Can be either PassThrough or Active. If PassThrough, Lambda will only trace the request from an upstream service if it contains a tracing header with "sampled=1". If Active, Lambda will respect any tracing header it receives from an upstream service. If no tracing header is received, Lambda will call X-Ray for a tracing decision. |
object({
mode = string
})
| `null` | no | -| [vpc\_config](#input\_vpc\_config) | Provide this to allow your function to access your VPC. | `any` | `null` | no | +| Name | Description | Type | Required | +|------|-------------|------|:--------:| +| [allowed\_services](#input\_allowed\_services) | A list of AWS Services that are allowed to access this lambda. | `list(string)` | no | +| [build\_command](#input\_build\_command) | This is the build command to execute. It can be provided as a relative path to the current working directory or as an absolute path. It is evaluated in a shell, and can use environment variables or Terraform variables. | `string` | no | +| [build\_triggers](#input\_build\_triggers) | A map of values which should cause the build command to re-run. Values are meant to be interpolated references to variables or attributes of other resources. | `map(string)` | no | +| [dead\_letter\_config](#input\_dead\_letter\_config) | Nested block to configure the function's dead letter queue. |
object({
target_arn = string
})
| no | +| [description](#input\_description) | Description of what your Lambda Function does. | `string` | no | +| [environment](#input\_environment) | A map that defines environment variables for the Lambda function. |
object({
variables = map(string)
})
| no | +| [exclude\_files](#input\_exclude\_files) | A list of directories or folders to ignore, e.g.
exclude\_files = ["test", "src/**/*.ts"] | `list(string)` | no | +| [function\_name](#input\_function\_name) | A unique name for your Lambda Function. | `string` | yes | +| [handler](#input\_handler) | The function entrypoint in your code. | `string` | yes | +| [iam\_role\_name\_prefix](#input\_iam\_role\_name\_prefix) | The prefix string for the name of IAM role for the lambda function. | `string` | no | +| [kms\_key\_id](#input\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data. | `string` | no | +| [layers](#input\_layers) | List of Lambda Layer Version ARNs (maximum of 5) to attach to your Lambda Function. | `list(string)` | no | +| [memory\_size](#input\_memory\_size) | Amount of memory in MB your Lambda Function can use at runtime. | `number` | no | +| [output\_path](#input\_output\_path) | A path to which the source directory is archived before uploading to AWS. | `string` | yes | +| [policy\_arns](#input\_policy\_arns) | A list of IAM policy ARNs attached to the lambda function. | `list(string)` | no | +| [publish](#input\_publish) | Whether to publish creation/change as new Lambda Function Version. | `bool` | no | +| [reserved\_concurrent\_executions](#input\_reserved\_concurrent\_executions) | The amount of reserved concurrent executions for this lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | no | +| [retention\_in\_days](#input\_retention\_in\_days) | Specifies the number of days you want to retain log events in the specified log group. | `number` | no | +| [runtime](#input\_runtime) | The identifier of the function's runtime. | `string` | yes | +| [source\_dir](#input\_source\_dir) | A path to the directory which contains source files. | `string` | yes | +| [tags](#input\_tags) | A mapping of tags to assign to resources. | `map(string)` | no | +| [timeout](#input\_timeout) | The maximum number of seconds the lambda function to run until timeout. | `number` | no | +| [tracing\_config](#input\_tracing\_config) | Can be either PassThrough or Active. If PassThrough, Lambda will only trace the request from an upstream service if it contains a tracing header with "sampled=1". If Active, Lambda will respect any tracing header it receives from an upstream service. If no tracing header is received, Lambda will call X-Ray for a tracing decision. |
object({
mode = string
})
| no | +| [vpc\_config](#input\_vpc\_config) | Provide this to allow your function to access your VPC. |
object({
security_group_ids = list(string)
subnet_ids = list(string)
})
| no | ## Outputs diff --git a/examples/simple-nodejs/outputs.tf b/examples/simple-nodejs/outputs.tf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/simple-nodejs/outputs.tf @@ -0,0 +1 @@ + diff --git a/examples/simple-nodejs/variables.tf b/examples/simple-nodejs/variables.tf index db54ea9..a2889e1 100644 --- a/examples/simple-nodejs/variables.tf +++ b/examples/simple-nodejs/variables.tf @@ -1,5 +1,6 @@ variable "region" { description = "The AWS region in which global resources are set up." + type = string default = "us-east-1" } diff --git a/examples/simple-py/outputs.tf b/examples/simple-py/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/simple-py/variables.tf b/examples/simple-py/variables.tf index db54ea9..a2889e1 100644 --- a/examples/simple-py/variables.tf +++ b/examples/simple-py/variables.tf @@ -1,5 +1,6 @@ variable "region" { description = "The AWS region in which global resources are set up." + type = string default = "us-east-1" } diff --git a/main.tf b/main.tf index 3b62ab9..bd97a5c 100644 --- a/main.tf +++ b/main.tf @@ -1,10 +1,31 @@ +terraform { + required_version = ">= 0.15.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.50.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.1.0" + } + archive = { + source = "hashicorp/archive" + version = ">= 2.2.0" + } + } +} + #--------------------------------------------------------------------------------------------------- # IAM role for Lambda function #--------------------------------------------------------------------------------------------------- + resource "aws_iam_role" "this" { name_prefix = var.iam_role_name_prefix assume_role_policy = data.aws_iam_policy_document.assume.json - tags = var.tags + + tags = var.tags } data "aws_iam_policy_document" "assume" { @@ -24,7 +45,8 @@ resource "aws_iam_role_policy_attachment" "basic" { } resource "aws_iam_role_policy_attachment" "vpc" { - count = var.vpc_config == null ? 0 : 1 + count = var.vpc_config == null ? 0 : 1 + role = aws_iam_role.this.name policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" } @@ -39,6 +61,7 @@ resource "aws_iam_role_policy_attachment" "lambda" { #--------------------------------------------------------------------------------------------------- # CloudWatch Log group #--------------------------------------------------------------------------------------------------- + resource "aws_cloudwatch_log_group" "this" { name = "/aws/lambda/${var.function_name}" retention_in_days = var.retention_in_days diff --git a/variables.tf b/variables.tf index 1c14234..ab072b3 100644 --- a/variables.tf +++ b/variables.tf @@ -1,8 +1,10 @@ #--------------------------------------------------------------------------------------------------- # General #--------------------------------------------------------------------------------------------------- + variable "tags" { description = "A mapping of tags to assign to resources." + type = map(string) default = { Terraform = "true" } @@ -11,6 +13,7 @@ variable "tags" { #--------------------------------------------------------------------------------------------------- # Build arguments #--------------------------------------------------------------------------------------------------- + variable "build_command" { description = "This is the build command to execute. It can be provided as a relative path to the current working directory or as an absolute path. It is evaluated in a shell, and can use environment variables or Terraform variables." type = string @@ -19,7 +22,8 @@ variable "build_command" { variable "build_triggers" { description = "A map of values which should cause the build command to re-run. Values are meant to be interpolated references to variables or attributes of other resources." - default = [] + type = map(string) + default = {} } variable "source_dir" { @@ -44,6 +48,7 @@ DESC #--------------------------------------------------------------------------------------------------- # IAM Role arguments #--------------------------------------------------------------------------------------------------- + variable "iam_role_name_prefix" { description = "The prefix string for the name of IAM role for the lambda function." type = string @@ -59,6 +64,7 @@ variable "policy_arns" { #--------------------------------------------------------------------------------------------------- # CloudWatch Log Group arguments #--------------------------------------------------------------------------------------------------- + variable "retention_in_days" { description = "Specifies the number of days you want to retain log events in the specified log group." type = number @@ -74,6 +80,7 @@ variable "kms_key_id" { #--------------------------------------------------------------------------------------------------- # Lambda arguments #--------------------------------------------------------------------------------------------------- + variable "function_name" { description = "A unique name for your Lambda Function." type = string @@ -118,8 +125,8 @@ variable "dead_letter_config" { } variable "description" { - type = string description = "Description of what your Lambda Function does." + type = string default = "" } @@ -131,13 +138,13 @@ variable "layers" { variable "reserved_concurrent_executions" { description = "The amount of reserved concurrent executions for this lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations." - type = string + type = number default = -1 } variable "publish" { description = "Whether to publish creation/change as new Lambda Function Version." - type = string + type = bool default = false } @@ -151,13 +158,12 @@ variable "tracing_config" { variable "vpc_config" { description = "Provide this to allow your function to access your VPC." - default = null -} + type = object({ + security_group_ids = list(string) + subnet_ids = list(string) + }) -variable "kms_key_arn" { - description = "The ARN for the KMS encryption key." - type = string - default = null + default = null } variable "allowed_services" {