Skip to content

Commit

Permalink
PLAT-5801: Allow bastion instance type to be specified (#13)
Browse files Browse the repository at this point in the history
Combine all bastion details into a single object.
The existence means you want to create the bastion.
  • Loading branch information
Michael Fraenkel authored Dec 2, 2022
1 parent e44fc56 commit 2f22f37
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- checkout

- terraform/install:
terraform_version: '1.3.4'
terraform_version: '1.3.5'

- terraform/fmt:
path: .
Expand Down
7 changes: 5 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.75.0
hooks:
- id: terraform_providers_lock
args:
- --tf-init-args=-upgrade
- id: terraform_fmt
- id: terraform_validate
- id: terraform_docs
args:
- '--hook-config=--path-to-file=README.md'
Expand All @@ -22,7 +27,6 @@ repos:
- '--hook-config=--recursive.enabled=true'
- '--hook-config=--recursive.path=submodules'
- '--hook-config=--lockfile=false'
- id: terraform_fmt
- id: terraform_tflint
args:
- '--args=--config=__GIT_WORKING_DIR__/.tflint.hcl'
Expand All @@ -39,7 +43,6 @@ repos:
- '--args=--only=terraform_required_providers'
- '--args=--only=terraform_standard_module_structure'
- '--args=--only=terraform_workspace_remote'
- id: terraform_validate
# - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed.
# args:
# - '--args=--non-recursive'
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 4.36.1 |
| <a name="provider_tls"></a> [tls](#provider\_tls) | 4.0.3 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 4.40.0 |
| <a name="provider_tls"></a> [tls](#provider\_tls) | 4.0.4 |

## Modules

Expand Down Expand Up @@ -111,9 +111,8 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force
|------|-------------|------|---------|:--------:|
| <a name="input_additional_node_groups"></a> [additional\_node\_groups](#input\_additional\_node\_groups) | Additional EKS managed node groups definition. | <pre>map(object({<br> ami = optional(string)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = list(string)<br> spot = optional(bool, false)<br> min_per_az = number<br> max_per_az = number<br> desired_per_az = number<br> labels = map(string)<br> taints = optional(list(object({ key = string, value = optional(string), effect = string })), [])<br> tags = optional(map(string), {})<br> volume = object({<br> size = string<br> type = string<br> })<br> }))</pre> | `{}` | no |
| <a name="input_availability_zones"></a> [availability\_zones](#input\_availability\_zones) | List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html.<br> Note that setting this variable bypasses validation of the status of the zones data 'aws\_availability\_zones' 'available'.<br> Caller is responsible for validating status of these zones. | `list(string)` | `[]` | no |
| <a name="input_bastion_ami_id"></a> [bastion\_ami\_id](#input\_bastion\_ami\_id) | AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon\_linux\_2' ami | `string` | `""` | no |
| <a name="input_bastion"></a> [bastion](#input\_bastion) | if specifed, a bastion is created with the specified details | <pre>object({<br> ami = optional(string, null) # default will use the latest 'amazon_linux_2' ami<br> instance_type = optional(string, "t2.micro")<br> })</pre> | `null` | no |
| <a name="input_cidr"></a> [cidr](#input\_cidr) | The IPv4 CIDR block for the VPC. | `string` | `"10.0.0.0/16"` | no |
| <a name="input_create_bastion"></a> [create\_bastion](#input\_create\_bastion) | Create bastion toggle. | `bool` | `false` | no |
| <a name="input_default_node_groups"></a> [default\_node\_groups](#input\_default\_node\_groups) | EKS managed node groups definition. | <pre>object(<br> {<br> compute = object(<br> {<br> ami = optional(string)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["m5.2xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 0)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 1)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "default"<br> })<br> taints = optional(list(object({ key = string, value = optional(string), effect = string })), [])<br> tags = optional(map(string), {})<br> volume = optional(object(<br> {<br> size = optional(number, 100)<br> type = optional(string, "gp3")<br> }),<br> {<br> size = 100<br> type = "gp3"<br> }<br> )<br> }),<br> platform = object(<br> {<br> ami = optional(string)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["m5.4xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 1)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 1)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "platform"<br> })<br> taints = optional(list(object({ key = string, value = optional(string), effect = string })), [])<br> tags = optional(map(string), {})<br> volume = optional(object(<br> {<br> size = optional(number, 100)<br> type = optional(string, "gp3")<br> }),<br> {<br> size = 100<br> type = "gp3"<br> }<br> )<br> }),<br> gpu = object(<br> {<br> ami = optional(string)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["g4dn.xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 0)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 0)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "default-gpu"<br> "nvidia.com/gpu" = true<br> })<br> taints = optional(list(object({ key = string, value = optional(string), effect = string })), [<br> { key = "nvidia.com/gpu", value = "true", effect = "NO_SCHEDULE" }<br> ])<br> tags = optional(map(string), {})<br> volume = optional(object(<br> {<br> size = optional(number, 100)<br> type = optional(string, "gp3")<br> }),<br> {<br> size = 100<br> type = "gp3"<br> }<br> )<br> })<br> })</pre> | <pre>{<br> "compute": {},<br> "gpu": {},<br> "platform": {}<br>}</pre> | no |
| <a name="input_deploy_id"></a> [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no |
| <a name="input_efs_access_point_path"></a> [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no |
Expand Down
23 changes: 12 additions & 11 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,16 @@ locals {
}

module "bastion" {
count = var.create_bastion ? 1 : 0
count = var.bastion != null ? 1 : 0

source = "./submodules/bastion"
deploy_id = var.deploy_id
region = var.region
vpc_id = local.vpc_id
ssh_pvt_key_path = aws_key_pair.domino.key_name
bastion_public_subnet_id = local.public_subnets[0].subnet_id
bastion_ami_id = var.bastion_ami_id
source = "./submodules/bastion"
deploy_id = var.deploy_id
region = var.region
vpc_id = local.vpc_id
ssh_pvt_key_path = aws_key_pair.domino.key_name
public_subnet_id = local.public_subnets[0].subnet_id
ami_id = var.bastion.ami
instance_type = var.bastion.instance_type
}

module "eks" {
Expand All @@ -131,7 +132,7 @@ module "eks" {
private_subnets = local.private_subnets
ssh_pvt_key_path = aws_key_pair.domino.key_name
bastion_security_group_id = try(module.bastion[0].security_group_id, "")
create_bastion_sg = var.create_bastion
create_bastion_sg = var.bastion != null
kubeconfig_path = local.kubeconfig_path
default_node_groups = var.default_node_groups
additional_node_groups = var.additional_node_groups
Expand All @@ -144,12 +145,12 @@ module "eks" {
}

data "aws_iam_role" "eks_master_roles" {
for_each = var.create_bastion ? toset(var.eks_master_role_names) : []
for_each = var.bastion != null ? toset(var.eks_master_role_names) : []
name = each.key
}

module "k8s_setup" {
count = var.create_bastion ? 1 : 0
count = var.bastion != null ? 1 : 0
source = "./submodules/k8s"
ssh_pvt_key_path = local.ssh_pvt_key_path
bastion_user = local.bastion_user
Expand Down
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ output "ssh_bastion_command" {

output "bastion_ip" {
description = "public ip of the bastion"
value = var.create_bastion ? module.bastion[0].public_ip : ""
value = var.bastion != null ? module.bastion[0].public_ip : ""
}

output "hostname" {
Expand Down
7 changes: 4 additions & 3 deletions submodules/bastion/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_bastion_ami_id"></a> [bastion\_ami\_id](#input\_bastion\_ami\_id) | AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon\_linux\_2' ami. | `string` | `""` | no |
| <a name="input_bastion_public_subnet_id"></a> [bastion\_public\_subnet\_id](#input\_bastion\_public\_subnet\_id) | Public subnet to create bastion host in. | `string` | n/a | yes |
| <a name="input_bastion_security_group_rules"></a> [bastion\_security\_group\_rules](#input\_bastion\_security\_group\_rules) | Bastion host security group rules. | <pre>map(object({<br> protocol = string<br> from_port = string<br> to_port = string<br> type = string<br> description = string<br> cidr_blocks = list(string)<br> source_security_group_id = string<br><br> }))</pre> | <pre>{<br> "bastion_inbound_ssh": {<br> "cidr_blocks": [<br> "0.0.0.0/0"<br> ],<br> "description": "Inbound ssh",<br> "from_port": "22",<br> "protocol": "-1",<br> "source_security_group_id": null,<br> "to_port": "22",<br> "type": "ingress"<br> },<br> "bastion_outbound_traffic": {<br> "cidr_blocks": [<br> "0.0.0.0/0"<br> ],<br> "description": "Allow all outbound traffic by default",<br> "from_port": "0",<br> "protocol": "-1",<br> "source_security_group_id": null,<br> "to_port": "0",<br> "type": "egress"<br> }<br>}</pre> | no |
| <a name="input_ami_id"></a> [ami\_id](#input\_ami\_id) | AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon\_linux\_2' ami. | `string` | `null` | no |
| <a name="input_deploy_id"></a> [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes |
| <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | the bastion's instance type, if null, t2.micro is used | `string` | `null` | no |
| <a name="input_public_subnet_id"></a> [public\_subnet\_id](#input\_public\_subnet\_id) | Public subnet to create bastion host in. | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes |
| <a name="input_security_group_rules"></a> [security\_group\_rules](#input\_security\_group\_rules) | Bastion host security group rules. | <pre>map(object({<br> protocol = string<br> from_port = string<br> to_port = string<br> type = string<br> description = string<br> cidr_blocks = list(string)<br> source_security_group_id = string<br><br> }))</pre> | <pre>{<br> "bastion_inbound_ssh": {<br> "cidr_blocks": [<br> "0.0.0.0/0"<br> ],<br> "description": "Inbound ssh",<br> "from_port": "22",<br> "protocol": "-1",<br> "source_security_group_id": null,<br> "to_port": "22",<br> "type": "ingress"<br> },<br> "bastion_outbound_traffic": {<br> "cidr_blocks": [<br> "0.0.0.0/0"<br> ],<br> "description": "Allow all outbound traffic by default",<br> "from_port": "0",<br> "protocol": "-1",<br> "source_security_group_id": null,<br> "to_port": "0",<br> "type": "egress"<br> }<br>}</pre> | no |
| <a name="input_ssh_pvt_key_path"></a> [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | n/a | yes |

Expand Down
12 changes: 6 additions & 6 deletions submodules/bastion/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ resource "aws_security_group" "bastion" {
}
}
resource "aws_security_group_rule" "bastion" {
for_each = var.bastion_security_group_rules
for_each = var.security_group_rules

security_group_id = aws_security_group.bastion.id
protocol = each.value.protocol
Expand Down Expand Up @@ -72,7 +72,7 @@ resource "aws_iam_instance_profile" "bastion" {
}

data "aws_ami" "amazon_linux_2" {
count = var.bastion_ami_id == "" ? 1 : 0
count = var.ami_id == null ? 1 : 0
most_recent = true
owners = ["amazon"]

Expand All @@ -83,11 +83,11 @@ data "aws_ami" "amazon_linux_2" {
}

locals {
bastion_ami_id = var.bastion_ami_id != "" ? var.bastion_ami_id : data.aws_ami.amazon_linux_2[0].id
ami_id = var.ami_id != null ? var.ami_id : data.aws_ami.amazon_linux_2[0].id
}

resource "aws_instance" "bastion" {
ami = local.bastion_ami_id
ami = local.ami_id
associate_public_ip_address = true
iam_instance_profile = aws_iam_instance_profile.bastion.name
monitoring = true
Expand All @@ -106,7 +106,7 @@ resource "aws_instance" "bastion" {
get_password_data = false
hibernation = false
instance_initiated_shutdown_behavior = "stop"
instance_type = "t2.micro"
instance_type = var.instance_type != null ? var.instance_type : "t2.micro"
key_name = var.ssh_pvt_key_path

metadata_options {
Expand All @@ -126,7 +126,7 @@ resource "aws_instance" "bastion" {
}

source_dest_check = true
subnet_id = var.bastion_public_subnet_id
subnet_id = var.public_subnet_id

vpc_security_group_ids = [aws_security_group.bastion.id]
tags = {
Expand Down
16 changes: 11 additions & 5 deletions submodules/bastion/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ variable "deploy_id" {
description = "Domino Deployment ID"
}

variable "bastion_ami_id" {
variable "ami_id" {
description = "AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon_linux_2' ami."
type = string
default = ""
default = null
}

variable "instance_type" {
description = "the bastion's instance type, if null, t2.micro is used"
type = string
default = null
}

variable "region" {
description = "AWS region for the deployment"
type = string
Expand All @@ -23,12 +30,12 @@ variable "ssh_pvt_key_path" {
type = string
}

variable "bastion_public_subnet_id" {
variable "public_subnet_id" {
description = "Public subnet to create bastion host in."
type = string
}

variable "bastion_security_group_rules" {
variable "security_group_rules" {

description = "Bastion host security group rules."
type = map(object({
Expand Down Expand Up @@ -62,5 +69,4 @@ variable "bastion_security_group_rules" {
source_security_group_id = null
}
}

}
2 changes: 1 addition & 1 deletion tests/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module "domino_eks" {
route53_hosted_zone_name = "deploys-delta.domino.tech"
eks_master_role_names = ["okta-poweruser", "okta-fulladmin"]
s3_force_destroy_on_deletion = true
create_bastion = true
bastion = {}
ssh_pvt_key_path = "domino.pem"
tags = var.tags
default_node_groups = {
Expand Down
18 changes: 7 additions & 11 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -224,23 +224,19 @@ variable "private_subnets" {
default = null
}

variable "create_bastion" {
type = bool
description = "Create bastion toggle."
default = false
}

variable "bastion_ami_id" {
description = "AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon_linux_2' ami"
type = string
default = ""
variable "bastion" {
type = object({
ami = optional(string, null) # default will use the latest 'amazon_linux_2' ami
instance_type = optional(string, "t2.micro")
})
description = "if specifed, a bastion is created with the specified details"
default = null
}

variable "efs_access_point_path" {
type = string
description = "Filesystem path for efs."
default = "/domino"

}

variable "ssh_pvt_key_path" {
Expand Down

0 comments on commit 2f22f37

Please sign in to comment.