Skip to content

Commit 3fe20b6

Browse files
dudymasBenbentwo
andauthored
feat: support network_stack parameter (#19)
* feat(external-net): added * chore(remote-state): tidy unused module * chore(external-net): update parameters * chore(src): format changes * chore(docs): updated for network_stack * fix(main/locals): tflint feedback on vpc_id * chore(docs): regenerated and abstract added * fix(subnets): adjusting for subnet errors * chore(readme): update yaml and version requirements --------- Co-authored-by: Ben <ben.smith.developer@gmail.com>
1 parent 8d2b785 commit 3fe20b6

File tree

7 files changed

+485
-145
lines changed

7 files changed

+485
-145
lines changed

README.md

Lines changed: 103 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.yaml

Lines changed: 142 additions & 54 deletions
Large diffs are not rendered by default.

src/README.md

Lines changed: 109 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.tf

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
locals {
22
enabled = module.this.enabled
33

4+
external_vpc_id = var.vpc_id != null ? { "ExternalVpcId" = var.vpc_id } : {}
5+
networking_stack = var.networking_stack != null ? { "NetworkingStack" = var.networking_stack } : {}
6+
subnet_ids = var.subnet_ids != null ? { "ExternalVpcSubnetIds" = var.subnet_ids } : {}
7+
external_security_group_id = var.security_group_id != null ? { "ExternalVpcSecurityGroupId" = var.security_group_id } : {}
8+
created_security_group_id = var.security_group_id == null && var.networking_stack == "external" ? { "ExternalVpcSecurityGroupId" = module.security_group.id } : {}
9+
410
parameters = merge({
511
"EC2InstanceCustomPolicy" = module.iam_policy.policy_arn
6-
}, var.parameters)
12+
}, var.parameters
13+
, local.networking_stack
14+
, local.external_vpc_id
15+
, local.subnet_ids
16+
, local.external_security_group_id
17+
, local.created_security_group_id
18+
)
719

820
}
921

@@ -56,6 +68,29 @@ module "iam_policy" {
5668
]
5769
}
5870

71+
module "security_group" {
72+
source = "cloudposse/security-group/aws"
73+
version = "2.2.0"
74+
75+
enabled = local.enabled && var.security_group_id == null && var.networking_stack == "external"
76+
77+
vpc_id = local.vpc_id
78+
79+
context = module.this.context
80+
}
81+
82+
resource "aws_security_group_rule" "this" {
83+
for_each = var.security_group_rules != null && local.enabled ? { for rule in var.security_group_rules : md5(jsonencode(rule)) => rule } : {}
84+
85+
security_group_id = local.security_group_id
86+
87+
type = each.value.type
88+
from_port = each.value.from_port
89+
to_port = each.value.to_port
90+
protocol = each.value.protocol
91+
cidr_blocks = each.value.cidr_blocks
92+
}
93+
5994
module "cloudformation_stack" {
6095
count = local.enabled ? 1 : 0
6196

@@ -75,24 +110,46 @@ module "cloudformation_stack" {
75110
depends_on = [module.iam_policy]
76111
}
77112

113+
data "aws_vpc" "this" {
114+
count = local.enabled ? 1 : 0
115+
id = local.vpc_id
116+
}
117+
118+
data "aws_subnets" "private" {
119+
count = local.enabled ? 1 : 0
120+
filter {
121+
name = "vpc-id"
122+
values = [local.vpc_id]
123+
}
124+
filter {
125+
name = "map-public-ip-on-launch"
126+
values = ["false"]
127+
}
128+
}
129+
130+
data "aws_subnets" "public" {
131+
count = local.enabled ? 1 : 0
132+
filter {
133+
name = "vpc-id"
134+
values = [local.vpc_id]
135+
}
136+
filter {
137+
name = "map-public-ip-on-launch"
138+
values = ["true"]
139+
}
140+
}
141+
78142
locals {
79-
vpc_id = one(module.cloudformation_stack[*].outputs["RunsOnVPCId"])
80-
vpc_cidr_block = one(module.cloudformation_stack[*].outputs["RunsOnVpcCidrBlock"])
81-
public_subnet_ids = compact([
82-
one(module.cloudformation_stack[*].outputs["RunsOnPublicSubnet1"]),
83-
one(module.cloudformation_stack[*].outputs["RunsOnPublicSubnet2"]),
84-
one(module.cloudformation_stack[*].outputs["RunsOnPublicSubnet3"]),
85-
])
86-
private_subnet_ids = compact([
87-
one(module.cloudformation_stack[*].outputs["RunsOnPrivateSubnet1"]),
88-
one(module.cloudformation_stack[*].outputs["RunsOnPrivateSubnet2"]),
89-
one(module.cloudformation_stack[*].outputs["RunsOnPrivateSubnet3"]),
90-
])
91-
private_route_table_ids = compact([
143+
vpc_id = var.networking_stack == "embedded" ? one(module.cloudformation_stack[*].outputs["RunsOnVPCId"]) : var.vpc_id
144+
vpc_cidr_block = var.networking_stack == "embedded" ? one(module.cloudformation_stack[*].outputs["RunsOnVpcCidrBlock"]) : one(data.aws_vpc.this[*].cidr_block)
145+
public_subnet_ids = one(data.aws_subnets.public[*].ids)
146+
private_subnet_ids = one(data.aws_subnets.private[*].ids)
147+
private_route_table_ids = var.networking_stack == "embedded" ? compact([
92148
one(module.cloudformation_stack[*].outputs["RunsOnPrivateRouteTable1Id"]),
93149
one(module.cloudformation_stack[*].outputs["RunsOnPrivateRouteTable2Id"]),
94150
one(module.cloudformation_stack[*].outputs["RunsOnPrivateRouteTable3Id"]),
95-
])
151+
]) : []
152+
security_group_id = one(module.cloudformation_stack[*].outputs["RunsOnSecurityGroupId"])
96153
}
97154

98155
data "aws_nat_gateways" "ngws" {

src/outputs.tf

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,27 @@ output "nat_gateway_ids" {
2828
description = "NAT Gateway IDs"
2929
}
3030

31-
// Required by TGW Component but not created by RunsOn CloudFormation Stack
31+
# Required by TGW Component but not created by RunsOn CloudFormation Stack
3232
output "nat_instance_ids" {
3333
value = []
3434
description = "NAT Instance IDs"
3535
}
3636

3737
output "private_subnet_ids" {
38-
value = local.private_subnet_ids
39-
# value = one(data.aws_subnets.private_subnets[*].ids)
38+
value = local.private_subnet_ids
4039
description = "Private subnet IDs"
4140
}
4241

4342
output "public_subnet_ids" {
44-
value = local.public_subnet_ids
45-
# value = one(data.aws_subnets.public_subnets[*].ids)
43+
value = local.public_subnet_ids
4644
description = "Public subnet IDs"
4745
}
4846

47+
output "security_group_id" {
48+
value = local.security_group_id
49+
description = "Security group ID"
50+
}
51+
4952
output "private_route_table_ids" {
5053
value = local.private_route_table_ids
5154
description = "Private subnet route table IDs"

src/remote-state.tf

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/variables.tf

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,55 @@ variable "policy_body" {
3838
description = "Structure containing the stack policy body"
3939
}
4040

41-
variable "vpc_peering_component" {
42-
default = null
43-
type = object({
44-
component = string
45-
environment = optional(string)
46-
tenant = optional(string)
47-
stage = optional(string)
48-
})
49-
description = "The component name of the VPC Peering Connection"
41+
variable "networking_stack" {
42+
type = string
43+
description = "Let RunsOn manage your networking stack (`embedded`), or use a vpc under your control (`external`). Null will default to whatever the template used as default. If you select `external`, you will need to provide the VPC ID, the subnet IDs, and optionally the security group ID, and make sure your whole networking setup is compatible with RunsOn (see https://runs-on.com/networking/embedded-vs-external/ for more details). To get started quickly, we recommend using the 'embedded' option."
44+
nullable = true
45+
default = "embedded"
46+
validation {
47+
condition = contains(["embedded", "external"], var.networking_stack) || var.networking_stack == null
48+
error_message = "Networking stack must be either `embedded` or `external`."
49+
}
50+
}
51+
52+
variable "vpc_id" {
53+
type = string
54+
description = "VPC ID"
55+
nullable = true
56+
default = null
57+
validation {
58+
condition = var.networking_stack != "external" || var.vpc_id != null
59+
error_message = "VPC ID is required when networking stack is `external`."
60+
}
61+
}
62+
63+
variable "subnet_ids" {
64+
type = list(string)
65+
description = "Subnet IDs"
66+
nullable = true
67+
default = null
68+
validation {
69+
condition = var.networking_stack != "external" || var.subnet_ids != null && length(var.subnet_ids) > 0
70+
error_message = "Subnet IDs are required when networking stack is `external`."
71+
}
72+
}
73+
74+
variable "security_group_id" {
75+
type = string
76+
description = "Security group ID. If not set, a new security group will be created."
77+
nullable = true
78+
default = null
79+
}
80+
81+
variable "security_group_rules" {
82+
type = list(object({
83+
type = string
84+
from_port = number
85+
to_port = number
86+
protocol = string
87+
cidr_blocks = list(string)
88+
}))
89+
description = "Security group rules. These are either added to the security passed in, or added to the security group created when var.security_group_id is not set. Types include `ingress` and `egress`."
90+
nullable = true
91+
default = null
5092
}

0 commit comments

Comments
 (0)