diff --git a/.gitignore b/.gitignore index 141171d..4381353 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,24 @@ -# ignored files +# Terraform state files - Contains sensitive infrastructure state information *.tfstate *.tfstate.backup + +# Local Terraform directory - Contains downloaded providers and modules .terraform + +# IDE settings directory for IntelliJ .idea + +# IntelliJ project files *.iml + +# Go dependency file go.sum + +# Terraform lock file - Contains provider version constraints *.terraform.lock.hcl + +# Terraform crash log file - Generated during crashes crash.log + +# Variable definitions files - May contain sensitive values +*.tfvars \ No newline at end of file diff --git a/README.yaml b/README.yaml index cdef558..c897675 100644 --- a/README.yaml +++ b/README.yaml @@ -82,7 +82,7 @@ usage: |- #Root Volume root_block_device = [ { - volume_type = "gp2" + volume_type = "gp3" volume_size = 15 delete_on_termination = true } @@ -90,7 +90,7 @@ usage: |- #EBS Volume ebs_volume_enabled = false - ebs_volume_type = "gp2" + ebs_volume_type = "gp3" ebs_volume_size = 30 #Tags @@ -131,7 +131,7 @@ usage: |- #Root Volume root_block_device = [ { - volume_type = "gp2" + volume_type = "gp3" volume_size = 15 delete_on_termination = true } @@ -139,7 +139,7 @@ usage: |- #EBS Volume ebs_volume_enabled = true - ebs_volume_type = "gp2" + ebs_volume_type = "gp3" ebs_volume_size = 30 #Tags @@ -187,7 +187,7 @@ usage: |- #Root Volume root_block_device = [ { - volume_type = "gp2" + volume_type = "gp3" volume_size = 15 delete_on_termination = true } @@ -195,7 +195,7 @@ usage: |- #EBS Volume ebs_volume_enabled = true - ebs_volume_type = "gp2" + ebs_volume_type = "gp3" ebs_volume_size = 30 #Tags diff --git a/docs/io.md b/docs/io.md index 463405c..9cf9f9e 100644 --- a/docs/io.md +++ b/docs/io.md @@ -28,7 +28,7 @@ | ebs\_optimized | If true, the launched EC2 instance will be EBS-optimized. | `bool` | `false` | no | | ebs\_volume\_enabled | Flag to control the ebs creation. | `bool` | `false` | no | | ebs\_volume\_size | Size of the EBS volume in gigabytes. | `number` | `30` | no | -| ebs\_volume\_type | The type of EBS volume. Can be standard, gp2 or io1. | `string` | `"gp2"` | no | +| ebs\_volume\_type | The type of EBS volume. Can be standard, gp3 or io1. | `string` | `"gp3"` | no | | egress\_ipv4\_cidr\_block | List of CIDR blocks. Cannot be specified with source\_security\_group\_id or self. | `list(string)` |
[| no | | egress\_ipv4\_from\_port | Egress Start port (or ICMP type number if protocol is icmp or icmpv6). | `number` | `0` | no | | egress\_ipv4\_protocol | Protocol. If not icmp, icmpv6, tcp, udp, or all use the protocol number | `string` | `"-1"` | no | diff --git a/examples/basic/example.tf b/examples/basic/example.tf index 0cf5274..3b4a2c0 100644 --- a/examples/basic/example.tf +++ b/examples/basic/example.tf @@ -16,8 +16,19 @@ module "ec2" { #instance instance_count = 1 - ami = "ami-08d658f84a6d84a80" - instance_type = "c4.xlarge" + instance_configuration = { + ami = "ami-08d658f84a6d84a80" + instance_type = "t4g.small" + + #Root Volume + root_block_device = [ + { + volume_type = "gp3" + volume_size = 15 + delete_on_termination = true + } + ] + } #Networking subnet_ids = ["subnet-xxxxxxxx"] @@ -28,14 +39,7 @@ module "ec2" { #IAM iam_instance_profile = "iam-profile-xxxxxxxxx" - #Root Volume - root_block_device = [ - { - volume_type = "gp2" - volume_size = 15 - delete_on_termination = true - } - ] + #Tags instance_tags = { "snapshot" = true } diff --git a/examples/complete/example.tf b/examples/complete/example.tf index d56f15c..8245268 100644 --- a/examples/complete/example.tf +++ b/examples/complete/example.tf @@ -91,8 +91,21 @@ module "ec2" { ssh_allowed_ports = [22] #Instance instance_count = 1 - ami = "ami-0f8e81a3da6e2510a" - instance_type = "t2.nano" + instance_configuration = { + ami = "ami-0f8e81a3da6e2510a" + instance_type = "t4g.small" + + #Root Volume + root_block_device = [ + { + volume_type = "gp3" + volume_size = 15 + delete_on_termination = true + } + ] + #Mount EBS With User Data + user_data = file("user-data.sh") + } #Keypair public_key = "" @@ -103,23 +116,15 @@ module "ec2" { #IAM iam_instance_profile = module.iam-role.name - #Root Volume - root_block_device = [ - { - volume_type = "gp2" - volume_size = 15 - delete_on_termination = true - } - ] + #EBS Volume ebs_volume_enabled = true - ebs_volume_type = "gp2" + ebs_volume_type = "gp3" ebs_volume_size = 30 #Tags instance_tags = { "snapshot" = true } - #Mount EBS With User Data - user_data = file("user-data.sh") + } \ No newline at end of file diff --git a/examples/spot_instance/example.tf b/examples/spot_instance/example.tf index f9e5e80..4eb6256 100644 --- a/examples/spot_instance/example.tf +++ b/examples/spot_instance/example.tf @@ -17,13 +17,23 @@ module "spot-ec2" { public_key = "" # Spot-instance - spot_price = "0.3" - spot_wait_for_fulfillment = true - spot_type = "persistent" - spot_instance_interruption_behavior = "terminate" - spot_instance_enabled = true - spot_instance_count = 1 - instance_type = "c4.xlarge" + spot_configuration = { + spot_price = "0.3" + wait_for_fulfillment = true + spot_type = "persistent" + instance_interruption_behavior = "terminate" + spot_instance_enabled = true + spot_instance_count = 1 + instance_type = "t4g.small" + + root_block_device = [ + { + volume_type = "gp3" + volume_size = 15 + delete_on_termination = true + } + ] + } #Networking subnet_ids = ["subnet-xxxxxxxx"] @@ -32,17 +42,10 @@ module "spot-ec2" { iam_instance_profile = "iam-profile-xxxxxxxxx" #Root Volume - root_block_device = [ - { - volume_type = "gp2" - volume_size = 15 - delete_on_termination = true - } - ] #EBS Volume ebs_volume_enabled = true - ebs_volume_type = "gp2" + ebs_volume_type = "gp3" ebs_volume_size = 30 #Tags diff --git a/main.tf b/main.tf index f061249..d32403b 100644 --- a/main.tf +++ b/main.tf @@ -148,33 +148,34 @@ data "aws_iam_policy_document" "kms" { #tfsec:ignore:aws-ec2-enforce-http-token-imds resource "aws_instance" "default" { count = var.enable && var.default_instance_enabled ? var.instance_count : 0 - ami = var.ami == "" ? data.aws_ami.ubuntu.id : var.ami - ebs_optimized = var.ebs_optimized - instance_type = var.instance_type + ami = var.instance_configuration.ami == "" ? data.aws_ami.ubuntu.id : var.instance_configuration.ami + ebs_optimized = var.instance_configuration.ebs_optimized + instance_type = var.instance_configuration.instance_type key_name = var.key_name == "" ? join("", aws_key_pair.default[*].key_name) : var.key_name - monitoring = var.monitoring + monitoring = var.instance_configuration.monitoring vpc_security_group_ids = length(var.sg_ids) < 1 ? aws_security_group.default[*].id : var.sg_ids subnet_id = element(distinct(compact(concat(var.subnet_ids))), count.index) - associate_public_ip_address = var.associate_public_ip_address - disable_api_termination = var.disable_api_termination - instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior - placement_group = var.placement_group - tenancy = var.tenancy - host_id = var.host_id - cpu_core_count = var.cpu_core_count - cpu_threads_per_core = var.cpu_threads_per_core - user_data = var.user_data - user_data_base64 = var.user_data_base64 - user_data_replace_on_change = var.user_data_replace_on_change - availability_zone = var.availability_zone - get_password_data = var.get_password_data - private_ip = var.private_ip - secondary_private_ips = var.secondary_private_ips + associate_public_ip_address = var.instance_configuration.associate_public_ip_address + disable_api_termination = var.instance_configuration.disable_api_termination + instance_initiated_shutdown_behavior = var.instance_configuration.instance_initiated_shutdown_behavior + placement_group = var.instance_configuration.placement_group + tenancy = var.instance_configuration.tenancy + host_id = var.instance_configuration.host_id + cpu_core_count = var.instance_configuration.cpu_core_count + cpu_threads_per_core = var.instance_configuration.cpu_threads_per_core + user_data = var.instance_configuration.user_data + user_data_base64 = var.instance_configuration.user_data_base64 + user_data_replace_on_change = var.instance_configuration.user_data_replace_on_change + availability_zone = var.instance_configuration.availability_zone + get_password_data = var.instance_configuration.get_password_data + private_ip = var.instance_configuration.private_ip + secondary_private_ips = var.instance_configuration.secondary_private_ips iam_instance_profile = join("", aws_iam_instance_profile.default[*].name) - source_dest_check = var.source_dest_check - ipv6_address_count = var.ipv6_address_count - ipv6_addresses = var.ipv6_addresses - hibernation = var.hibernation + source_dest_check = var.instance_configuration.source_dest_check + ipv6_address_count = var.instance_configuration.ipv6_address_count + ipv6_addresses = var.instance_configuration.ipv6_addresses + hibernation = var.instance_configuration.hibernation + dynamic "cpu_options" { for_each = length(var.cpu_options) > 0 ? [var.cpu_options] : [] content { @@ -199,7 +200,7 @@ resource "aws_instance" "default" { } dynamic "root_block_device" { - for_each = var.root_block_device + for_each = var.instance_configuration.root_block_device content { delete_on_termination = lookup(root_block_device.value, "delete_on_termination", null) encrypted = true @@ -226,7 +227,7 @@ resource "aws_instance" "default" { kms_key_id = var.kms_key_id == "" ? join("", aws_kms_key.default[*].arn) : lookup(ebs_block_device.value, "kms_key_id", null) snapshot_id = lookup(ebs_block_device.value, "snapshot_id", null) volume_size = lookup(ebs_block_device.value, "volume_size", null) - volume_type = lookup(ebs_block_device.value, "volume_type", "gp2") + volume_type = lookup(ebs_block_device.value, "volume_type", "gp3") throughput = lookup(ebs_block_device.value, "throughput", null) tags = merge(module.labels.tags, { @@ -238,7 +239,7 @@ resource "aws_instance" "default" { } dynamic "ephemeral_block_device" { - for_each = var.ephemeral_block_device + for_each = var.instance_configuration.ephemeral_block_device content { device_name = ephemeral_block_device.value.device_name no_device = lookup(ephemeral_block_device.value, "no_device", null) @@ -372,42 +373,44 @@ resource "aws_route53_record" "default" { ## Below Provides an EC2 Spot Instance Request resource. This allows instances to be requested on the spot market.. ##---------------------------------------------------------------------------------- resource "aws_spot_instance_request" "default" { - count = var.enable && var.spot_instance_enabled ? var.spot_instance_count : 0 - spot_price = var.spot_price - wait_for_fulfillment = var.spot_wait_for_fulfillment - spot_type = var.spot_type - launch_group = var.spot_launch_group - block_duration_minutes = var.spot_block_duration_minutes - instance_interruption_behavior = var.spot_instance_interruption_behavior - valid_until = var.spot_valid_until - valid_from = var.spot_valid_from - ami = var.ami == "" ? data.aws_ami.ubuntu.id : var.ami - ebs_optimized = var.ebs_optimized - instance_type = var.instance_type + count = var.enable && var.spot_instance_enabled ? var.spot_instance_count : 0 + spot_price = var.spot_configuration.spot_price + wait_for_fulfillment = var.spot_configuration.wait_for_fulfillment + spot_type = var.spot_configuration.spot_type + launch_group = var.spot_configuration.launch_group + block_duration_minutes = var.spot_configuration.block_duration_minutes + instance_interruption_behavior = var.spot_configuration.instance_interruption_behavior + valid_until = var.spot_configuration.valid_until + valid_from = var.spot_configuration.valid_from + + # Instance configuration + ami = var.instance_configuration.ami == "" ? data.aws_ami.ubuntu.id : var.instance_configuration.ami + ebs_optimized = var.instance_configuration.ebs_optimized + instance_type = var.instance_configuration.instance_type key_name = var.key_name == "" ? join("", aws_key_pair.default[*].key_name) : var.key_name - monitoring = var.monitoring + monitoring = var.instance_configuration.monitoring vpc_security_group_ids = length(var.sg_ids) < 1 ? aws_security_group.default[*].id : var.sg_ids subnet_id = element(distinct(compact(concat(var.subnet_ids))), count.index) - associate_public_ip_address = var.associate_public_ip_address - disable_api_termination = var.disable_api_termination - instance_initiated_shutdown_behavior = var.instance_initiated_shutdown_behavior - placement_group = var.placement_group - tenancy = var.tenancy - host_id = var.host_id - cpu_core_count = var.cpu_core_count - cpu_threads_per_core = var.cpu_threads_per_core - user_data = var.user_data - user_data_base64 = var.user_data_base64 - user_data_replace_on_change = var.user_data_replace_on_change - availability_zone = var.availability_zone - get_password_data = var.get_password_data - private_ip = var.private_ip - secondary_private_ips = var.secondary_private_ips + associate_public_ip_address = var.instance_configuration.associate_public_ip_address + disable_api_termination = var.instance_configuration.disable_api_termination + instance_initiated_shutdown_behavior = var.instance_configuration.instance_initiated_shutdown_behavior + placement_group = var.instance_configuration.placement_group + tenancy = var.instance_configuration.tenancy + host_id = var.instance_configuration.host_id + cpu_core_count = var.instance_configuration.cpu_core_count + cpu_threads_per_core = var.instance_configuration.cpu_threads_per_core + user_data = var.instance_configuration.user_data + user_data_base64 = var.instance_configuration.user_data_base64 + user_data_replace_on_change = var.instance_configuration.user_data_replace_on_change + availability_zone = var.instance_configuration.availability_zone + get_password_data = var.instance_configuration.get_password_data + private_ip = var.instance_configuration.private_ip + secondary_private_ips = var.instance_configuration.secondary_private_ips iam_instance_profile = join("", aws_iam_instance_profile.default[*].name) - source_dest_check = var.source_dest_check - ipv6_address_count = var.ipv6_address_count - ipv6_addresses = var.ipv6_addresses - hibernation = var.hibernation + source_dest_check = var.instance_configuration.source_dest_check + ipv6_address_count = var.instance_configuration.ipv6_address_count + ipv6_addresses = var.instance_configuration.ipv6_addresses + hibernation = var.instance_configuration.hibernation dynamic "cpu_options" { for_each = length(var.cpu_options) > 0 ? [var.cpu_options] : [] @@ -433,7 +436,7 @@ resource "aws_spot_instance_request" "default" { } dynamic "root_block_device" { - for_each = var.root_block_device + for_each = var.instance_configuration.root_block_device content { delete_on_termination = lookup(root_block_device.value, "delete_on_termination", null) encrypted = true @@ -472,7 +475,7 @@ resource "aws_spot_instance_request" "default" { } dynamic "ephemeral_block_device" { - for_each = var.ephemeral_block_device + for_each = var.instance_configuration.ephemeral_block_device content { device_name = ephemeral_block_device.value.device_name no_device = lookup(ephemeral_block_device.value, "no_device", null) diff --git a/variables.tf b/variables.tf index 2728408..a749755 100644 --- a/variables.tf +++ b/variables.tf @@ -56,82 +56,38 @@ variable "enable" { description = "Flag to control module creation." } -variable "ami" { - type = string - default = "" - description = "The AMI to use for the instance." -} - -variable "ebs_optimized" { - type = bool - default = false - description = "If true, the launched EC2 instance will be EBS-optimized." -} - -variable "instance_type" { - type = string - description = "The type of instance to start. Updates to this field will trigger a stop/start of the EC2 instance." -} - -variable "monitoring" { - type = bool - default = false - description = "If true, the launched EC2 instance will have detailed monitoring enabled. (Available since v0.6.0)." -} - -variable "associate_public_ip_address" { - type = bool - default = true - description = "Associate a public IP address with the instance." - sensitive = true -} - -variable "ephemeral_block_device" { - type = list(any) - default = [] - description = "Customize Ephemeral (also known as Instance Store) volumes on the instance." -} - -variable "disable_api_termination" { - type = bool - default = false - description = "If true, enables EC2 Instance Termination Protection." -} - -variable "instance_initiated_shutdown_behavior" { - type = string - default = "stop" - description = "(Optional) 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 instances. See Shutdown Behavior for more information." -} - -variable "placement_group" { - type = string - default = "" - description = "The Placement Group to start the instance in." -} - -variable "tenancy" { - type = string - default = "default" - description = "The tenancy of the instance (if the instance is running in a VPC). An instance with a tenancy of dedicated runs on single-tenant hardware. The host tenancy is not supported for the import-instance command." -} - -variable "root_block_device" { - type = list(any) - default = [] - description = "Customize details about the root block device of the instance. See Block Devices below for details." -} - -variable "user_data" { - type = string - default = "" - description = "(Optional) A string of the desired User Data for the ec2." -} - -variable "user_data_base64" { - description = "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" - type = string - default = null +variable "instance_configuration" { + description = "Configuration options for the EC2 instance" + type = object({ + ami = optional(string, "") + ebs_optimized = optional(bool, false) + instance_type = string + monitoring = optional(bool, false) + associate_public_ip_address = optional(bool, true) + disable_api_termination = optional(bool, false) + instance_initiated_shutdown_behavior = optional(string, "stop") + placement_group = optional(string, "") + tenancy = optional(string, "default") + host_id = optional(string, null) + cpu_core_count = optional(number, null) + cpu_threads_per_core = optional(number, null) + user_data = optional(string, "") + user_data_base64 = optional(string, null) + user_data_replace_on_change = optional(bool, null) + availability_zone = optional(string, null) + get_password_data = optional(bool, null) + private_ip = optional(string, null) + secondary_private_ips = optional(list(string), null) + source_dest_check = optional(bool, true) + ipv6_address_count = optional(number, null) + ipv6_addresses = optional(list(string), null) + hibernation = optional(bool, false) + root_block_device = optional(list(any), []) + ephemeral_block_device = optional(list(any), []) + }) + default = { + instance_type = "t4g.small" # Providing a default instance type + } } variable "assign_eip_address" { @@ -161,8 +117,8 @@ variable "ebs_volume_size" { variable "ebs_volume_type" { type = string - default = "gp2" - description = "The type of EBS volume. Can be standard, gp2 or io1." + default = "gp3" + description = "The type of EBS volume. Can be standard, gp3 or io1." } variable "default_instance_enabled" { @@ -195,25 +151,6 @@ variable "instance_count" { description = "Number of instances to launch." } -variable "source_dest_check" { - type = bool - default = true - description = "Controls if traffic is routed to the instance when the destination address does not match the instance. Used for NAT or VPNs." -} - -variable "ipv6_address_count" { - type = number - default = null - description = "Number of IPv6 addresses to associate with the primary network interface. Amazon EC2 chooses the IPv6 addresses from the range of your subnet." -} - -variable "ipv6_addresses" { - type = list(any) - default = null - description = "List of IPv6 addresses from the range of the subnet to associate with the primary network interface." - sensitive = true -} - variable "network_interface" { description = "Customize network interfaces to be attached at instance boot time" type = list(map(string)) @@ -221,18 +158,6 @@ variable "network_interface" { } -variable "host_id" { - type = string - default = null - description = "The 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." -} - -variable "cpu_core_count" { - type = string - default = null - description = "Sets the number of CPU cores for an instance." -} - variable "iam_instance_profile" { type = string default = null @@ -312,12 +237,6 @@ variable "instance_metadata_tags_enabled" { description = "Whether the metadata tag is available. Valid values include enabled or disabled. Defaults to enabled." } -variable "hibernation" { - type = bool - default = false - description = "hibernate an instance, Amazon EC2 signals the operating system to perform hibernation." -} - variable "multi_attach_enabled" { type = bool default = false @@ -509,88 +428,19 @@ variable "spot_instance_count" { description = "Number of instances to launch." } -variable "spot_price" { - type = string - default = null - description = "The maximum price to request on the spot market. Defaults to on-demand price" -} - -variable "spot_wait_for_fulfillment" { - type = bool - default = false - description = "If set, Terraform will wait for the Spot Request to be fulfilled, and will throw an error if the timeout of 10m is reached" -} - -variable "spot_type" { - type = string - default = null - description = "If set to one-time, after the instance is terminated, the spot request will be closed. Default `persistent`" -} - -variable "spot_launch_group" { - type = string - default = null - description = "A launch group is a group of spot instances that launch together and terminate together. If left empty instances are launched and terminated individually" -} - -variable "spot_block_duration_minutes" { - type = number - default = null - description = "The required duration for the Spot instances, in minutes. This value must be a multiple of 60 (60, 120, 180, 240, 300, or 360)" -} - -variable "spot_instance_interruption_behavior" { - type = string - default = null - description = "Indicates Spot instance behavior when it is interrupted. Valid values are `terminate`, `stop`, or `hibernate`" -} - -variable "spot_valid_until" { - type = string - default = null - description = "The end date and time of the request, in UTC RFC3339 format(for example, YYYY-MM-DDTHH:MM:SSZ)" -} - -variable "spot_valid_from" { - type = string - default = null - description = "The start date and time of the request, in UTC RFC3339 format(for example, YYYY-MM-DDTHH:MM:SSZ)" -} - -variable "cpu_threads_per_core" { - description = "Sets the number of CPU threads per core for an instance (has no effect unless cpu_core_count is also set)" - type = number - default = null -} - -variable "user_data_replace_on_change" { - description = "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" - type = bool - default = null -} - -variable "availability_zone" { - description = "AZ to start the instance in" - type = string - default = null -} - -variable "get_password_data" { - description = "If true, wait for password data to become available and retrieve it" - type = bool - default = null -} - -variable "private_ip" { - description = "Private IP address to associate with the instance in a VPC" - type = string - default = null -} - -variable "secondary_private_ips" { - description = "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`" - type = list(string) - default = null +variable "spot_configuration" { + description = "Configuration options for the EC2 spot instance" + type = object({ + spot_price = optional(string, null) + wait_for_fulfillment = optional(bool, false) + spot_type = optional(string, null) + launch_group = optional(string, null) + block_duration_minutes = optional(number, null) + instance_interruption_behavior = optional(string, null) + valid_until = optional(string, null) + valid_from = optional(string, null) + }) + default = {} } variable "cpu_options" {
"0.0.0.0/0"
]