diff --git a/README.md b/README.md index 8f22cb7d..97dd257a 100644 --- a/README.md +++ b/README.md @@ -1,309 +1,431 @@ -# AWS EC2 Instance Terraform module +# terraform-docs -Terraform module which creates an EC2 instance on AWS. +[![Build Status](https://github.com/terraform-docs/terraform-docs/workflows/ci/badge.svg)](https://github.com/terraform-docs/terraform-docs/actions) [![GoDoc](https://pkg.go.dev/badge/github.com/terraform-docs/terraform-docs)](https://pkg.go.dev/github.com/terraform-docs/terraform-docs) [![Go Report Card](https://goreportcard.com/badge/github.com/terraform-docs/terraform-docs)](https://goreportcard.com/report/github.com/terraform-docs/terraform-docs) [![Codecov Report](https://codecov.io/gh/terraform-docs/terraform-docs/branch/master/graph/badge.svg)](https://codecov.io/gh/terraform-docs/terraform-docs) [![License](https://img.shields.io/github/license/terraform-docs/terraform-docs)](https://github.com/terraform-docs/terraform-docs/blob/master/LICENSE) [![Latest release](https://img.shields.io/github/v/release/terraform-docs/terraform-docs)](https://github.com/terraform-docs/terraform-docs/releases) -[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) +![terraform-docs-teaser](./images/terraform-docs-teaser.png) -## Usage +## What is terraform-docs -### Single EC2 Instance +A utility to generate documentation from Terraform modules in various output formats. -```hcl -module "ec2_instance" { - source = "terraform-aws-modules/ec2-instance/aws" +## Installation - name = "single-instance" +macOS users can install using [Homebrew]: - instance_type = "t2.micro" - key_name = "user1" - monitoring = true - vpc_security_group_ids = ["sg-12345678"] - subnet_id = "subnet-eddcdzz4" +```bash +brew install terraform-docs +``` - tags = { - Terraform = "true" - Environment = "dev" - } -} +or + +```bash +brew install terraform-docs/tap/terraform-docs ``` -### Multiple EC2 Instance +Windows users can install using [Scoop]: -```hcl -module "ec2_instance" { - source = "terraform-aws-modules/ec2-instance/aws" +```bash +scoop bucket add terraform-docs https://github.com/terraform-docs/scoop-bucket +scoop install terraform-docs +``` - for_each = toset(["one", "two", "three"]) +or [Chocolatey]: - name = "instance-${each.key}" +```bash +choco install terraform-docs +``` - instance_type = "t2.micro" - key_name = "user1" - monitoring = true - vpc_security_group_ids = ["sg-12345678"] - subnet_id = "subnet-eddcdzz4" +Stable binaries are also available on the [releases] page. To install, download the +binary for your platform from "Assets" and place this into your `$PATH`: - tags = { - Terraform = "true" - Environment = "dev" - } -} +```bash +curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.17.0/terraform-docs-v0.17.0-$(uname)-amd64.tar.gz +tar -xzf terraform-docs.tar.gz +chmod +x terraform-docs +mv terraform-docs /usr/local/bin/terraform-docs ``` -### Spot EC2 Instance +**NOTE:** Windows releases are in `ZIP` format. -```hcl -module "ec2_instance" { - source = "terraform-aws-modules/ec2-instance/aws" +The latest version can be installed using `go install` or `go get`: - name = "spot-instance" +```bash +# go1.17+ +go install github.com/terraform-docs/terraform-docs@v0.17.0 +``` - create_spot_instance = true - spot_price = "0.60" - spot_type = "persistent" +```bash +# go1.16 +GO111MODULE="on" go get github.com/terraform-docs/terraform-docs@v0.17.0 +``` - instance_type = "t2.micro" - key_name = "user1" - monitoring = true - vpc_security_group_ids = ["sg-12345678"] - subnet_id = "subnet-eddcdzz4" +**NOTE:** please use the latest Go to do this, minimum `go1.16` is required. - tags = { - Terraform = "true" - Environment = "dev" - } -} +This will put `terraform-docs` in `$(go env GOPATH)/bin`. If you encounter the error +`terraform-docs: command not found` after installation then you may need to either add +that directory to your `$PATH` as shown [here] or do a manual installation by cloning +the repo and run `make build` from the repository which will put `terraform-docs` in: + +```bash +$(go env GOPATH)/src/github.com/terraform-docs/terraform-docs/bin/$(uname | tr '[:upper:]' '[:lower:]')-amd64/terraform-docs ``` -## Module wrappers +## Usage -Users of this Terraform module can create multiple similar resources by using [`for_each` meta-argument within `module` block](https://www.terraform.io/language/meta-arguments/for_each) which became available in Terraform 0.13. +### Running the binary directly -Users of Terragrunt can achieve similar results by using modules provided in the [wrappers](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/wrappers) directory, if they prefer to reduce amount of configuration files. +To run and generate documentation into README within a directory: -## Examples +```bash +terraform-docs markdown table --output-file README.md --output-mode inject /path/to/module +``` -- [Complete EC2 instance](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/complete) -- [EC2 instance w/ private network access via Session Manager](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/session-manager) -- [EC2 instance with EBS volume attachment](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/volume-attachment) +Check [`output`] configuration for more details and examples. -## Make an encrypted AMI for use +### Using docker -This module does not support encrypted AMI's out of the box however it is easy enough for you to generate one for use +terraform-docs can be run as a container by mounting a directory with `.tf` +files in it and run the following command: -This example creates an encrypted image from the latest ubuntu 16.04 base image. +```bash +docker run --rm --volume "$(pwd):/terraform-docs" -u $(id -u) quay.io/terraform-docs/terraform-docs:0.17.0 markdown /terraform-docs +``` -```hcl -provider "aws" { - region = "us-west-2" -} +If `output.file` is not enabled for this module, generated output can be redirected +back to a file: -data "aws_ami" "ubuntu" { - most_recent = true - owners = ["679593333241"] +```bash +docker run --rm --volume "$(pwd):/terraform-docs" -u $(id -u) quay.io/terraform-docs/terraform-docs:0.17.0 markdown /terraform-docs > doc.md +``` - filter { - name = "name" - values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"] - } +**NOTE:** Docker tag `latest` refers to _latest_ stable released version and `edge` +refers to HEAD of `master` at any given point in time. + +### Using GitHub Actions + +To use terraform-docs GitHub Action, configure a YAML workflow file (e.g. +`.github/workflows/documentation.yml`) with the following: + +```yaml +name: Generate terraform docs +on: + - pull_request + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Render terraform docs and push changes back to PR + uses: terraform-docs/gh-actions@main + with: + working-dir: . + output-file: README.md + output-method: inject + git-push: "true" +``` - filter { - name = "virtualization-type" - values = ["hvm"] - } -} +Read more about [terraform-docs GitHub Action] and its configuration and +examples. -resource "aws_ami_copy" "ubuntu_encrypted_ami" { - name = "ubuntu-encrypted-ami" - description = "An encrypted root ami based off ${data.aws_ami.ubuntu.id}" - source_ami_id = data.aws_ami.ubuntu.id - source_ami_region = "eu-west-2" - encrypted = true +### pre-commit hook - tags = { Name = "ubuntu-encrypted-ami" } -} +With pre-commit, you can ensure your Terraform module documentation is kept +up-to-date each time you make a commit. -data "aws_ami" "encrypted-ami" { - most_recent = true +First [install pre-commit] and then create or update a `.pre-commit-config.yaml` +in the root of your Git repo with at least the following content: - filter { - name = "name" - values = [aws_ami_copy.ubuntu_encrypted_ami.id] - } +```yaml +repos: + - repo: https://github.com/terraform-docs/terraform-docs + rev: "v0.17.0" + hooks: + - id: terraform-docs-go + args: ["markdown", "table", "--output-file", "README.md", "./mymodule/path"] +``` - owners = ["self"] -} +Then run: + +```bash +pre-commit install +pre-commit install-hooks +``` + +Further changes to your module's `.tf` files will cause an update to documentation +when you make a commit. + +## Configuration + +terraform-docs can be configured with a yaml file. The default name of this file is +`.terraform-docs.yml` and the path order for locating it is: + +1. root of module directory +1. `.config/` folder at root of module directory +1. current directory +1. `.config/` folder at current directory +1. `$HOME/.tfdocs.d/` + +```yaml +formatter: "" # this is required + +version: "" + +header-from: main.tf +footer-from: "" + +recursive: + enabled: false + path: modules + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true ``` -## Conditional creation +## Content Template + +Generated content can be customized further away with `content` in configuration. +If the `content` is empty the default order of sections is used. + +Compatible formatters for customized content are `asciidoc` and `markdown`. `content` +will be ignored for other formatters. + +`content` is a Go template with following additional variables: + +- `{{ .Header }}` +- `{{ .Footer }}` +- `{{ .Inputs }}` +- `{{ .Modules }}` +- `{{ .Outputs }}` +- `{{ .Providers }}` +- `{{ .Requirements }}` +- `{{ .Resources }}` + +and following functions: + +- `{{ include "relative/path/to/file" }}` + +These variables are the generated output of individual sections in the selected +formatter. For example `{{ .Inputs }}` is Markdown Table representation of _inputs_ +when formatter is set to `markdown table`. + +Note that sections visibility (i.e. `sections.show` and `sections.hide`) takes +precedence over the `content`. + +Additionally there's also one extra special variable avaialble to the `content`: + +- `{{ .Module }}` + +As opposed to the other variables mentioned above, which are generated sections +based on a selected formatter, the `{{ .Module }}` variable is just a `struct` +representing a [Terraform module]. + +````yaml +content: |- + Any arbitrary text can be placed anywhere in the content + + {{ .Header }} + + and even in between sections -The following combinations are supported to conditionally create resources: + {{ .Providers }} -- Disable resource creation (no resources created): + and they don't even need to be in the default order -```hcl - create = false + {{ .Outputs }} + + include any relative files + + {{ include "relative/path/to/file" }} + + {{ .Inputs }} + + # Examples + + ```hcl + {{ include "examples/foo/main.tf" }} + ``` + + ## Resources + + {{ range .Module.Resources }} + - {{ .GetMode }}.{{ .Spec }} ({{ .Position.Filename }}#{{ .Position.Line }}) + {{- end }} +```` + +## Build on top of terraform-docs + +terraform-docs primary use-case is to be utilized as a standalone binary, but +some parts of it is also available publicly and can be imported in your project +as a library. + +```go +import ( + "github.com/terraform-docs/terraform-docs/format" + "github.com/terraform-docs/terraform-docs/print" + "github.com/terraform-docs/terraform-docs/terraform" +) + +// buildTerraformDocs for module root `path` and provided content `tmpl`. +func buildTerraformDocs(path string, tmpl string) (string, error) { + config := print.DefaultConfig() + config.ModuleRoot = path // module root path (can be relative or absolute) + + module, err := terraform.LoadWithOptions(config) + if err != nil { + return "", err + } + + // Generate in Markdown Table format + formatter := format.NewMarkdownTable(config) + + if err := formatter.Generate(module); err != nil { + return "", err + } + + // // Note: if you don't intend to provide additional template for the generated + // // content, or the target format doesn't provide templating (e.g. json, yaml, + // // xml, or toml) you can use `Content()` function instead of `Render()`. + // // `Content()` returns all the sections combined with predefined order. + // return formatter.Content(), nil + + return formatter.Render(tmpl) +} ``` -- Create spot instance: +## Plugin + +Generated output can be heavily customized with [`content`], but if using that +is not enough for your use-case, you can write your own plugin. + +In order to install a plugin the following steps are needed: -```hcl - create_spot_instance = true +- download the plugin and place it in `~/.tfdocs.d/plugins` (or `./.tfdocs.d/plugins`) +- make sure the plugin file name is `tfdocs-format-` +- modify [`formatter`] of `.terraform-docs.yml` file to be `` + +**Important notes:** + +- if the plugin file name is different than the example above, terraform-docs won't +be able to to pick it up nor register it properly +- you can only use plugin thorough `.terraform-docs.yml` file and it cannot be used +with CLI arguments + +To create a new plugin create a new repository called `tfdocs-format-` with +following `main.go`: + +```go +package main + +import ( + _ "embed" //nolint + + "github.com/terraform-docs/terraform-docs/plugin" + "github.com/terraform-docs/terraform-docs/print" + "github.com/terraform-docs/terraform-docs/template" + "github.com/terraform-docs/terraform-docs/terraform" +) + +func main() { + plugin.Serve(&plugin.ServeOpts{ + Name: "", + Version: "0.1.0", + Printer: printerFunc, + }) +} + +//go:embed sections.tmpl +var tplCustom []byte + +// printerFunc the function being executed by the plugin client. +func printerFunc(config *print.Config, module *terraform.Module) (string, error) { + tpl := template.New(config, + &template.Item{Name: "custom", Text: string(tplCustom)}, + ) + + rendered, err := tpl.Render("custom", module) + if err != nil { + return "", err + } + + return rendered, nil +} ``` -## Notes - -- `network_interface` can't be specified together with `vpc_security_group_ids`, `associate_public_ip_address`, `subnet_id`. See [complete example](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/complete) for details. -- Changes in `ebs_block_device` argument will be ignored. Use [aws_volume_attachment](https://www.terraform.io/docs/providers/aws/r/volume_attachment.html) resource to attach and detach volumes from AWS EC2 instances. See [this example](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/examples/volume-attachment). -- In regards to spot instances, you must grant the `AWSServiceRoleForEC2Spot` service-linked role access to any custom KMS keys, otherwise your spot request and instances will fail with `bad parameters`. You can see more details about why the request failed by using the awscli and `aws ec2 describe-spot-instance-requests` - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 4.66 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | >= 4.66 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_instance.ignore_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | -| [aws_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | -| [aws_spot_instance_request.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/spot_instance_request) | resource | -| [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | -| [aws_ssm_parameter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | ID of AMI to use for the instance | `string` | `null` | no | -| [ami\_ssm\_parameter](#input\_ami\_ssm\_parameter) | SSM parameter name for the AMI ID. For Amazon Linux AMI SSM parameters see [reference](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-public-parameters-ami.html) | `string` | `"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"` | no | -| [associate\_public\_ip\_address](#input\_associate\_public\_ip\_address) | Whether to associate a public IP address with an instance in a VPC | `bool` | `null` | no | -| [availability\_zone](#input\_availability\_zone) | AZ to start the instance in | `string` | `null` | no | -| [capacity\_reservation\_specification](#input\_capacity\_reservation\_specification) | Describes an instance's Capacity Reservation targeting option | `any` | `{}` | no | -| [cpu\_core\_count](#input\_cpu\_core\_count) | Sets the number of CPU cores for an instance | `number` | `null` | no | -| [cpu\_credits](#input\_cpu\_credits) | The credit option for CPU usage (unlimited or standard) | `string` | `null` | no | -| [cpu\_options](#input\_cpu\_options) | Defines CPU options to apply to the instance at launch time. | `any` | `{}` | no | -| [cpu\_threads\_per\_core](#input\_cpu\_threads\_per\_core) | Sets the number of CPU threads per core for an instance (has no effect unless cpu\_core\_count is also set) | `number` | `null` | no | -| [create](#input\_create) | Whether to create an instance | `bool` | `true` | no | -| [create\_iam\_instance\_profile](#input\_create\_iam\_instance\_profile) | Determines whether an IAM instance profile is created or to use an existing IAM instance profile | `bool` | `false` | no | -| [create\_spot\_instance](#input\_create\_spot\_instance) | Depicts if the instance is a spot instance | `bool` | `false` | no | -| [disable\_api\_stop](#input\_disable\_api\_stop) | If true, enables EC2 Instance Stop Protection | `bool` | `null` | no | -| [disable\_api\_termination](#input\_disable\_api\_termination) | If true, enables EC2 Instance Termination Protection | `bool` | `null` | no | -| [ebs\_block\_device](#input\_ebs\_block\_device) | Additional EBS block devices to attach to the instance | `list(any)` | `[]` | no | -| [ebs\_optimized](#input\_ebs\_optimized) | If true, the launched EC2 instance will be EBS-optimized | `bool` | `null` | no | -| [enable\_volume\_tags](#input\_enable\_volume\_tags) | Whether to enable volume tags (if enabled it conflicts with root\_block\_device tags) | `bool` | `true` | no | -| [enclave\_options\_enabled](#input\_enclave\_options\_enabled) | Whether Nitro Enclaves will be enabled on the instance. Defaults to `false` | `bool` | `null` | no | -| [ephemeral\_block\_device](#input\_ephemeral\_block\_device) | Customize Ephemeral (also known as Instance Store) volumes on the instance | `list(map(string))` | `[]` | no | -| [get\_password\_data](#input\_get\_password\_data) | If true, wait for password data to become available and retrieve it | `bool` | `null` | no | -| [hibernation](#input\_hibernation) | If true, the launched EC2 instance will support hibernation | `bool` | `null` | no | -| [host\_id](#input\_host\_id) | ID of a dedicated host that the instance will be assigned to. Use when an instance is to be launched on a specific dedicated host | `string` | `null` | no | -| [iam\_instance\_profile](#input\_iam\_instance\_profile) | IAM Instance Profile to launch the instance with. Specified as the name of the Instance Profile | `string` | `null` | no | -| [iam\_role\_description](#input\_iam\_role\_description) | Description of the role | `string` | `null` | no | -| [iam\_role\_name](#input\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no | -| [iam\_role\_path](#input\_iam\_role\_path) | IAM role path | `string` | `null` | no | -| [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no | -| [iam\_role\_policies](#input\_iam\_role\_policies) | Policies attached to the IAM role | `map(string)` | `{}` | no | -| [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role/profile created | `map(string)` | `{}` | no | -| [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name` or `name`) is used as a prefix | `bool` | `true` | no | -| [ignore\_ami\_changes](#input\_ignore\_ami\_changes) | Whether changes to the AMI ID changes should be ignored by Terraform. Note - changing this value will result in the replacement of the instance | `bool` | `false` | no | -| [instance\_initiated\_shutdown\_behavior](#input\_instance\_initiated\_shutdown\_behavior) | Shutdown behavior for the instance. Amazon defaults this to stop for EBS-backed instances and terminate for instance-store instances. Cannot be set on instance-store instance | `string` | `null` | no | -| [instance\_tags](#input\_instance\_tags) | Additional tags for the instance | `map(string)` | `{}` | no | -| [instance\_type](#input\_instance\_type) | The type of instance to start | `string` | `"t3.micro"` | no | -| [ipv6\_address\_count](#input\_ipv6\_address\_count) | A number of IPv6 addresses to associate with the primary network interface. Amazon EC2 chooses the IPv6 addresses from the range of your subnet | `number` | `null` | no | -| [ipv6\_addresses](#input\_ipv6\_addresses) | Specify one or more IPv6 addresses from the range of the subnet to associate with the primary network interface | `list(string)` | `null` | no | -| [key\_name](#input\_key\_name) | Key name of the Key Pair to use for the instance; which can be managed using the `aws_key_pair` resource | `string` | `null` | no | -| [launch\_template](#input\_launch\_template) | Specifies a Launch Template to configure the instance. Parameters configured on this resource will override the corresponding parameters in the Launch Template | `map(string)` | `{}` | no | -| [maintenance\_options](#input\_maintenance\_options) | The maintenance options for the instance | `any` | `{}` | no | -| [metadata\_options](#input\_metadata\_options) | Customize the metadata options of the instance | `map(string)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "optional"
}
| no | -| [monitoring](#input\_monitoring) | If true, the launched EC2 instance will have detailed monitoring enabled | `bool` | `null` | no | -| [name](#input\_name) | Name to be used on EC2 instance created | `string` | `""` | no | -| [network\_interface](#input\_network\_interface) | Customize network interfaces to be attached at instance boot time | `list(map(string))` | `[]` | no | -| [placement\_group](#input\_placement\_group) | The Placement Group to start the instance in | `string` | `null` | no | -| [private\_dns\_name\_options](#input\_private\_dns\_name\_options) | Customize the private DNS name options of the instance | `map(string)` | `{}` | no | -| [private\_ip](#input\_private\_ip) | Private IP address to associate with the instance in a VPC | `string` | `null` | no | -| [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | -| [root\_block\_device](#input\_root\_block\_device) | Customize details about the root block device of the instance. See Block Devices below for details | `list(any)` | `[]` | no | -| [secondary\_private\_ips](#input\_secondary\_private\_ips) | A list of secondary private IPv4 addresses to assign to the instance's primary network interface (eth0) in a VPC. Can only be assigned to the primary network interface (eth0) attached at instance creation, not a pre-existing network interface i.e. referenced in a `network_interface block` | `list(string)` | `null` | no | -| [source\_dest\_check](#input\_source\_dest\_check) | Controls if traffic is routed to the instance when the destination address does not match the instance. Used for NAT or VPNs | `bool` | `null` | no | -| [spot\_block\_duration\_minutes](#input\_spot\_block\_duration\_minutes) | The required duration for the Spot instances, in minutes. This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360) | `number` | `null` | no | -| [spot\_instance\_interruption\_behavior](#input\_spot\_instance\_interruption\_behavior) | Indicates Spot instance behavior when it is interrupted. Valid values are `terminate`, `stop`, or `hibernate` | `string` | `null` | no | -| [spot\_launch\_group](#input\_spot\_launch\_group) | A launch group is a group of spot instances that launch together and terminate together. If left empty instances are launched and terminated individually | `string` | `null` | no | -| [spot\_price](#input\_spot\_price) | The maximum price to request on the spot market. Defaults to on-demand price | `string` | `null` | no | -| [spot\_type](#input\_spot\_type) | If set to one-time, after the instance is terminated, the spot request will be closed. Default `persistent` | `string` | `null` | no | -| [spot\_valid\_from](#input\_spot\_valid\_from) | The start date and time of the request, in UTC RFC3339 format(for example, YYYY-MM-DDTHH:MM:SSZ) | `string` | `null` | no | -| [spot\_valid\_until](#input\_spot\_valid\_until) | The end date and time of the request, in UTC RFC3339 format(for example, YYYY-MM-DDTHH:MM:SSZ) | `string` | `null` | no | -| [spot\_wait\_for\_fulfillment](#input\_spot\_wait\_for\_fulfillment) | If set, Terraform will wait for the Spot Request to be fulfilled, and will throw an error if the timeout of 10m is reached | `bool` | `null` | no | -| [subnet\_id](#input\_subnet\_id) | The VPC Subnet ID to launch in | `string` | `null` | no | -| [tags](#input\_tags) | A mapping of tags to assign to the resource | `map(string)` | `{}` | no | -| [tenancy](#input\_tenancy) | The tenancy of the instance (if the instance is running in a VPC). Available values: default, dedicated, host | `string` | `null` | no | -| [timeouts](#input\_timeouts) | Define maximum timeout for creating, updating, and deleting EC2 instance resources | `map(string)` | `{}` | no | -| [user\_data](#input\_user\_data) | The user data to provide when launching the instance. Do not pass gzip-compressed data via this argument; see user\_data\_base64 instead | `string` | `null` | no | -| [user\_data\_base64](#input\_user\_data\_base64) | Can be used instead of user\_data to pass base64-encoded binary data directly. Use this instead of user\_data whenever the value is not a valid UTF-8 string. For example, gzip-encoded user data must be base64-encoded and passed via this argument to avoid corruption | `string` | `null` | no | -| [user\_data\_replace\_on\_change](#input\_user\_data\_replace\_on\_change) | When used in combination with user\_data or user\_data\_base64 will trigger a destroy and recreate when set to true. Defaults to false if not set | `bool` | `null` | no | -| [volume\_tags](#input\_volume\_tags) | A mapping of tags to assign to the devices created by the instance at launch time | `map(string)` | `{}` | no | -| [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | A list of security group IDs to associate with | `list(string)` | `null` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [ami](#output\_ami) | AMI ID that was used to create the instance | -| [arn](#output\_arn) | The ARN of the instance | -| [availability\_zone](#output\_availability\_zone) | The availability zone of the created instance | -| [capacity\_reservation\_specification](#output\_capacity\_reservation\_specification) | Capacity reservation specification of the instance | -| [ebs\_block\_device](#output\_ebs\_block\_device) | EBS block device information | -| [ephemeral\_block\_device](#output\_ephemeral\_block\_device) | Ephemeral block device information | -| [iam\_instance\_profile\_arn](#output\_iam\_instance\_profile\_arn) | ARN assigned by AWS to the instance profile | -| [iam\_instance\_profile\_id](#output\_iam\_instance\_profile\_id) | Instance profile's ID | -| [iam\_instance\_profile\_unique](#output\_iam\_instance\_profile\_unique) | Stable and unique string identifying the IAM instance profile | -| [iam\_role\_arn](#output\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the IAM role | -| [iam\_role\_name](#output\_iam\_role\_name) | The name of the IAM role | -| [iam\_role\_unique\_id](#output\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role | -| [id](#output\_id) | The ID of the instance | -| [instance\_state](#output\_instance\_state) | The state of the instance | -| [ipv6\_addresses](#output\_ipv6\_addresses) | The IPv6 address assigned to the instance, if applicable | -| [outpost\_arn](#output\_outpost\_arn) | The ARN of the Outpost the instance is assigned to | -| [password\_data](#output\_password\_data) | Base-64 encoded encrypted password data for the instance. Useful for getting the administrator password for instances running Microsoft Windows. This attribute is only exported if `get_password_data` is true | -| [primary\_network\_interface\_id](#output\_primary\_network\_interface\_id) | The ID of the instance's primary network interface | -| [private\_dns](#output\_private\_dns) | The private DNS name assigned to the instance. Can only be used inside the Amazon EC2, and only available if you've enabled DNS hostnames for your VPC | -| [private\_ip](#output\_private\_ip) | The private IP address assigned to the instance | -| [public\_dns](#output\_public\_dns) | The public DNS name assigned to the instance. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC | -| [public\_ip](#output\_public\_ip) | The public IP address assigned to the instance, if applicable. NOTE: If you are using an aws\_eip with your instance, you should refer to the EIP's address directly and not use `public_ip` as this field will change after the EIP is attached | -| [root\_block\_device](#output\_root\_block\_device) | Root block device information | -| [spot\_bid\_status](#output\_spot\_bid\_status) | The current bid status of the Spot Instance Request | -| [spot\_instance\_id](#output\_spot\_instance\_id) | The Instance ID (if any) that is currently fulfilling the Spot Instance request | -| [spot\_request\_state](#output\_spot\_request\_state) | The current request state of the Spot Instance Request | -| [tags\_all](#output\_tags\_all) | A map of tags assigned to the resource, including those inherited from the provider default\_tags configuration block | - - -## Authors - -Module is maintained by [Anton Babenko](https://github.com/antonbabenko) with help from [these awesome contributors](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/graphs/contributors). +Please refer to [tfdocs-format-template] for more details. You can create a new +repository from it by clicking on `Use this template` button. -## License +## Documentation -Apache 2 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-ec2-instance/tree/master/LICENSE) for full details. +- **Users** + - Read the [User Guide] to learn how to use terraform-docs + - Read the [Formats Guide] to learn about different output formats of terraform-docs + - Refer to [Config File Reference] for all the available configuration options +- **Developers** + - Read [Contributing Guide] before submitting a pull request -## Additional information for users from Russia and Belarus +Visit [our website] for all documentation. + +## Community + +- Discuss terraform-docs on [Slack] + +## License -* Russia has [illegally annexed Crimea in 2014](https://en.wikipedia.org/wiki/Annexation_of_Crimea_by_the_Russian_Federation) and [brought the war in Donbas](https://en.wikipedia.org/wiki/War_in_Donbas) followed by [full-scale invasion of Ukraine in 2022](https://en.wikipedia.org/wiki/2022_Russian_invasion_of_Ukraine). -* Russia has brought sorrow and devastations to millions of Ukrainians, killed hundreds of innocent people, damaged thousands of buildings, and forced several million people to flee. -* [Putin khuylo!](https://en.wikipedia.org/wiki/Putin_khuylo!) +MIT License - Copyright (c) 2021 The terraform-docs Authors. + +[Chocolatey]: https://www.chocolatey.org +[Config File Reference]: https://terraform-docs.io/user-guide/configuration/ +[`content`]: https://terraform-docs.io/user-guide/configuration/content/ +[Contributing Guide]: CONTRIBUTING.md +[Formats Guide]: https://terraform-docs.io/reference/terraform-docs/ +[`formatter`]: https://terraform-docs.io/user-guide/configuration/formatter/ +[here]: https://golang.org/doc/code.html#GOPATH +[Homebrew]: https://brew.sh +[install pre-commit]: https://pre-commit.com/#install +[`output`]: https://terraform-docs.io/user-guide/configuration/output/ +[releases]: https://github.com/terraform-docs/terraform-docs/releases +[Scoop]: https://scoop.sh/ +[Slack]: https://slack.terraform-docs.io/ +[terraform-docs GitHub Action]: https://github.com/terraform-docs/gh-actions +[Terraform module]: https://pkg.go.dev/github.com/terraform-docs/terraform-docs/terraform#Module +[tfdocs-format-template]: https://github.com/terraform-docs/tfdocs-format-template +[our website]: https://terraform-docs.io/ +[User Guide]: https://terraform-docs.io/user-guide/introduction/ diff --git a/examples/launch-template/README.md b/examples/launch-template/README.md new file mode 100644 index 00000000..abee31e3 --- /dev/null +++ b/examples/launch-template/README.md @@ -0,0 +1,77 @@ +# Complete EC2 instance + +Configuration in this directory creates EC2 instances with different sets of arguments (with Elastic IP, with network interface attached, with credit specifications). + +## Usage + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example may create resources which can cost money. Run `terraform destroy` when you don't need these resources. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.66 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.37.0 | +| [tls](#provider\_tls) | 4.0.5 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [ec2\_from\_launch\_template](#module\_ec2\_from\_launch\_template) | ../../ | n/a | +| [security\_group](#module\_security\_group) | terraform-aws-modules/security-group/aws | ~> 4.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_key_pair.tf_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource | +| [aws_launch_template.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [tls_private_key.ed25519](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource | +| [aws_ami.amazon_linux_23](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [ec2\_arn](#output\_ec2\_arn) | The ARN of the instance | +| [ec2\_availability\_zone](#output\_ec2\_availability\_zone) | The availability zone of the created instance | +| [ec2\_capacity\_reservation\_specification](#output\_ec2\_capacity\_reservation\_specification) | Capacity reservation specification of the instance | +| [ec2\_ebs\_block\_device](#output\_ec2\_ebs\_block\_device) | EBS block device information | +| [ec2\_ephemeral\_block\_device](#output\_ec2\_ephemeral\_block\_device) | Ephemeral block device information | +| [ec2\_iam\_instance\_profile\_arn](#output\_ec2\_iam\_instance\_profile\_arn) | ARN assigned by AWS to the instance profile | +| [ec2\_iam\_instance\_profile\_id](#output\_ec2\_iam\_instance\_profile\_id) | Instance profile's ID | +| [ec2\_iam\_instance\_profile\_unique](#output\_ec2\_iam\_instance\_profile\_unique) | Stable and unique string identifying the IAM instance profile | +| [ec2\_iam\_role\_arn](#output\_ec2\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the IAM role | +| [ec2\_iam\_role\_name](#output\_ec2\_iam\_role\_name) | The name of the IAM role | +| [ec2\_iam\_role\_unique\_id](#output\_ec2\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role | +| [ec2\_id](#output\_ec2\_id) | The ID of the instance | +| [ec2\_instance\_state](#output\_ec2\_instance\_state) | The state of the instance. One of: `pending`, `running`, `shutting-down`, `terminated`, `stopping`, `stopped` | +| [ec2\_primary\_network\_interface\_id](#output\_ec2\_primary\_network\_interface\_id) | The ID of the instance's primary network interface | +| [ec2\_private\_dns](#output\_ec2\_private\_dns) | The private DNS name assigned to the instance. Can only be used inside the Amazon EC2, and only available if you've enabled DNS hostnames for your VPC | +| [ec2\_public\_dns](#output\_ec2\_public\_dns) | The public DNS name assigned to the instance. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC | +| [ec2\_public\_ip](#output\_ec2\_public\_ip) | The public IP address assigned to the instance, if applicable. NOTE: If you are using an aws\_eip with your instance, you should refer to the EIP's address directly and not use `public_ip` as this field will change after the EIP is attached | +| [ec2\_root\_block\_device](#output\_ec2\_root\_block\_device) | Root block device information | +| [ec2\_tags\_all](#output\_ec2\_tags\_all) | A map of tags assigned to the resource, including those inherited from the provider default\_tags configuration block | + diff --git a/examples/launch-template/main.tf b/examples/launch-template/main.tf new file mode 100644 index 00000000..cd90cf3c --- /dev/null +++ b/examples/launch-template/main.tf @@ -0,0 +1,109 @@ +provider "aws" { + region = local.region +} + +data "aws_availability_zones" "available" {} + +locals { + name = "ex-${basename(path.cwd)}" + region = "eu-west-1" + + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + + user_data = <<-EOT + #!/bin/bash + echo "Hello Terraform!" + EOT + + tags = { + Name = local.name + Example = local.name + Repository = "https://github.com/terraform-aws-modules/terraform-aws-ec2-instance" + } +} + +################################################################################ +# EC2 Module +################################################################################ + +module "ec2_from_launch_template" { + source = "../../" + + name = local.name + + launch_template = { + id = aws_launch_template.this.id + } + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.0" + + name = local.name + cidr = local.vpc_cidr + + azs = local.azs + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)] + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)] + + tags = local.tags +} + +data "aws_ami" "amazon_linux_23" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["al2023-ami-2023*-x86_64"] + } +} + +module "security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 4.0" + + name = local.name + description = "Security group for example usage with EC2 instance" + vpc_id = module.vpc.vpc_id + + ingress_cidr_blocks = ["0.0.0.0/0"] + ingress_rules = ["http-80-tcp", "all-icmp"] + egress_rules = ["all-all"] + + tags = local.tags +} + +resource "tls_private_key" "ed25519" { + algorithm = "ED25519" +} + +resource "aws_key_pair" "tf_key" { + key_name = "terraform-ec2-instances-example" + public_key = tls_private_key.ed25519.public_key_openssh +} + +resource "aws_launch_template" "this" { + image_id = data.aws_ami.amazon_linux_23.id + instance_type = "c5.large" + key_name = aws_key_pair.tf_key.key_name + user_data = local.user_data + + network_interfaces { + security_groups = [module.security_group.security_group_id] + subnet_id = module.vpc.private_subnets[0] + } + + tag_specifications { + resource_type = "instance" + tags = local.tags + } +} diff --git a/examples/launch-template/outputs.tf b/examples/launch-template/outputs.tf new file mode 100644 index 00000000..79628ee6 --- /dev/null +++ b/examples/launch-template/outputs.tf @@ -0,0 +1,94 @@ +output "ec2_id" { + description = "The ID of the instance" + value = module.ec2_from_launch_template.id +} + +output "ec2_arn" { + description = "The ARN of the instance" + value = module.ec2_from_launch_template.arn +} + +output "ec2_capacity_reservation_specification" { + description = "Capacity reservation specification of the instance" + value = module.ec2_from_launch_template.capacity_reservation_specification +} + +output "ec2_instance_state" { + description = "The state of the instance. One of: `pending`, `running`, `shutting-down`, `terminated`, `stopping`, `stopped`" + value = module.ec2_from_launch_template.instance_state +} + +output "ec2_primary_network_interface_id" { + description = "The ID of the instance's primary network interface" + value = module.ec2_from_launch_template.primary_network_interface_id +} + +output "ec2_private_dns" { + description = "The private DNS name assigned to the instance. Can only be used inside the Amazon EC2, and only available if you've enabled DNS hostnames for your VPC" + value = module.ec2_from_launch_template.private_dns +} + +output "ec2_public_dns" { + description = "The public DNS name assigned to the instance. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC" + value = module.ec2_from_launch_template.public_dns +} + +output "ec2_public_ip" { + description = "The public IP address assigned to the instance, if applicable. NOTE: If you are using an aws_eip with your instance, you should refer to the EIP's address directly and not use `public_ip` as this field will change after the EIP is attached" + value = module.ec2_from_launch_template.public_ip +} + +output "ec2_tags_all" { + description = "A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block" + value = module.ec2_from_launch_template.tags_all +} + +output "ec2_iam_role_name" { + description = "The name of the IAM role" + value = module.ec2_from_launch_template.iam_role_name +} + +output "ec2_iam_role_arn" { + description = "The Amazon Resource Name (ARN) specifying the IAM role" + value = module.ec2_from_launch_template.iam_role_arn +} + +output "ec2_iam_role_unique_id" { + description = "Stable and unique string identifying the IAM role" + value = module.ec2_from_launch_template.iam_role_unique_id +} + +output "ec2_iam_instance_profile_arn" { + description = "ARN assigned by AWS to the instance profile" + value = module.ec2_from_launch_template.iam_instance_profile_arn +} + +output "ec2_iam_instance_profile_id" { + description = "Instance profile's ID" + value = module.ec2_from_launch_template.iam_instance_profile_id +} + +output "ec2_iam_instance_profile_unique" { + description = "Stable and unique string identifying the IAM instance profile" + value = module.ec2_from_launch_template.iam_instance_profile_unique +} + +output "ec2_root_block_device" { + description = "Root block device information" + value = module.ec2_from_launch_template.root_block_device +} + +output "ec2_ebs_block_device" { + description = "EBS block device information" + value = module.ec2_from_launch_template.ebs_block_device +} + +output "ec2_ephemeral_block_device" { + description = "Ephemeral block device information" + value = module.ec2_from_launch_template.ephemeral_block_device +} + +output "ec2_availability_zone" { + description = "The availability zone of the created instance" + value = module.ec2_from_launch_template.availability_zone +} diff --git a/examples/launch-template/variables.tf b/examples/launch-template/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/examples/launch-template/versions.tf b/examples/launch-template/versions.tf new file mode 100644 index 00000000..fd4d1167 --- /dev/null +++ b/examples/launch-template/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.66" + } + } +} diff --git a/main.tf b/main.tf index 2f291307..000eabdb 100644 --- a/main.tf +++ b/main.tf @@ -21,8 +21,8 @@ data "aws_ssm_parameter" "this" { resource "aws_instance" "this" { count = local.create && !var.ignore_ami_changes && !var.create_spot_instance ? 1 : 0 - ami = local.ami - instance_type = var.instance_type + ami = length(var.launch_template) == 0 ? local.ami : null + instance_type = length(var.launch_template) == 0 ? var.instance_type : null cpu_core_count = var.cpu_core_count cpu_threads_per_core = var.cpu_threads_per_core hibernation = var.hibernation @@ -199,8 +199,8 @@ resource "aws_instance" "this" { resource "aws_instance" "ignore_ami" { count = local.create && var.ignore_ami_changes && !var.create_spot_instance ? 1 : 0 - ami = local.ami - instance_type = var.instance_type + ami = length(var.launch_template) == 0 ? local.ami : null + instance_type = length(var.launch_template) == 0 ? var.instance_type : null cpu_core_count = var.cpu_core_count cpu_threads_per_core = var.cpu_threads_per_core hibernation = var.hibernation @@ -383,8 +383,8 @@ resource "aws_instance" "ignore_ami" { resource "aws_spot_instance_request" "this" { count = local.create && var.create_spot_instance ? 1 : 0 - ami = local.ami - instance_type = var.instance_type + ami = length(var.launch_template) == 0 ? local.ami : null + instance_type = length(var.launch_template) == 0 ? var.instance_type : null cpu_core_count = var.cpu_core_count cpu_threads_per_core = var.cpu_threads_per_core hibernation = var.hibernation