20482: Allows deploying on known VPC & subnets.
authorLucas Di Pentima <lucas.dipentima@curii.com>
Tue, 9 May 2023 00:10:09 +0000 (21:10 -0300)
committerLucas Di Pentima <lucas.dipentima@curii.com>
Tue, 9 May 2023 15:24:51 +0000 (12:24 -0300)
Instead of creating everything new, the admin now has the option to deploy
the resources on preexisting networks.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima@curii.com>

tools/salt-install/terraform/aws/services/outputs.tf
tools/salt-install/terraform/aws/vpc/locals.tf
tools/salt-install/terraform/aws/vpc/main.tf
tools/salt-install/terraform/aws/vpc/outputs.tf
tools/salt-install/terraform/aws/vpc/terraform.tfvars
tools/salt-install/terraform/aws/vpc/variables.tf

index 9dbccf81ced586b7e101e0072b655497cb2fa02d..8ff12c71b77748e34e483d447a55917bddd515d3 100644 (file)
@@ -6,10 +6,6 @@ output "vpc_id" {
   value = data.terraform_remote_state.vpc.outputs.arvados_vpc_id
 }
 
-output "vpc_cidr" {
-  value = data.terraform_remote_state.vpc.outputs.arvados_vpc_cidr
-}
-
 output "arvados_subnet_id" {
   value = data.terraform_remote_state.vpc.outputs.public_subnet_id
 }
index eb0371a35b1416029a2857c0c4dec1000a407056..017e5d4b8f13494aeaae111aa1cc38de86821f77 100644 (file)
@@ -12,6 +12,15 @@ locals {
   route53_public_zone = one(aws_route53_zone.public_zone[*])
   iam_user_letsencrypt = one(aws_iam_user.letsencrypt[*])
   iam_access_key_letsencrypt = one(aws_iam_access_key.letsencrypt[*])
+
+  arvados_vpc_id = one(aws_vpc.arvados_vpc[*]) != null ? one(aws_vpc.arvados_vpc[*]).id : var.vpc_id
+  arvados_vpc_cidr_block = one(aws_vpc.arvados_vpc[*])
+
+  arvados_sg_id = one(aws_security_group.arvados_sg[*]) != null ? one(aws_security_group.arvados_sg[*]).id : var.sg_id
+
+  private_subnet_id = one(aws_subnet.private_subnet[*]) != null ? one(aws_subnet.private_subnet[*]).id : var.private_subnet_id
+  public_subnet_id = one(aws_subnet.public_subnet[*]) != null ? one(aws_subnet.public_subnet[*]).id : var.public_subnet_id
+
   public_hosts = var.private_only ? [] : var.user_facing_hosts
   private_hosts = concat(
     var.internal_service_hosts,
index a5eb02049b0261a0e8692487a3488468d75cbd02..be5e57490dff9487ceb0737ac8256f30f527339f 100644 (file)
@@ -20,38 +20,64 @@ provider "aws" {
 }
 
 resource "aws_vpc" "arvados_vpc" {
+  count = var.vpc_id == "" ? 1 : 0
   cidr_block = "10.1.0.0/16"
   enable_dns_hostnames = true
   enable_dns_support = true
+
+  lifecycle {
+    precondition {
+      condition = (var.sg_id == "")
+      error_message = "vpc_id should be set if sg_id is also set"
+    }
+  }
 }
 resource "aws_subnet" "public_subnet" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.public_subnet_id == "" ? 1 : 0
+  vpc_id = local.arvados_vpc_id
   availability_zone = local.availability_zone
   cidr_block = "10.1.1.0/24"
+
+  lifecycle {
+    precondition {
+      condition = (var.vpc_id == "")
+      error_message = "public_subnet_id should be set if vpc_id is also set"
+    }
+  }
 }
 resource "aws_subnet" "private_subnet" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.private_subnet_id == "" ? 1 : 0
+  vpc_id = local.arvados_vpc_id
   availability_zone = local.availability_zone
   cidr_block = "10.1.2.0/24"
+
+  lifecycle {
+    precondition {
+      condition = (var.vpc_id == "")
+      error_message = "private_subnet_id should be set if vpc_id is also set"
+    }
+  }
 }
 
 #
 # VPC S3 access
 #
 resource "aws_vpc_endpoint" "s3" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  vpc_id = local.arvados_vpc_id
   service_name = "com.amazonaws.${var.region_name}.s3"
 }
 resource "aws_vpc_endpoint_route_table_association" "compute_s3_route" {
+  count = var.private_subnet_id == "" ? 1 : 0
   vpc_endpoint_id = aws_vpc_endpoint.s3.id
-  route_table_id = aws_route_table.private_subnet_rt.id
+  route_table_id = aws_route_table.private_subnet_rt[0].id
 }
 
 #
 # Internet access for Public IP instances
 #
 resource "aws_internet_gateway" "internet_gw" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.vpc_id == "" ? 1 : 0
+  vpc_id = local.arvados_vpc_id
 }
 resource "aws_eip" "arvados_eip" {
   for_each = toset(local.public_hosts)
@@ -60,45 +86,59 @@ resource "aws_eip" "arvados_eip" {
   ]
 }
 resource "aws_route_table" "public_subnet_rt" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.public_subnet_id == "" ? 1 : 0
+  vpc_id = local.arvados_vpc_id
   route {
     cidr_block = "0.0.0.0/0"
-    gateway_id = aws_internet_gateway.internet_gw.id
+    gateway_id = aws_internet_gateway.internet_gw[0].id
   }
 }
 resource "aws_route_table_association" "public_subnet_assoc" {
-  subnet_id = aws_subnet.public_subnet.id
-  route_table_id = aws_route_table.public_subnet_rt.id
+  count = var.public_subnet_id == "" ? 1 : 0
+  subnet_id = aws_subnet.public_subnet[0].id
+  route_table_id = aws_route_table.public_subnet_rt[0].id
 }
 
 #
 # Internet access for Private IP instances
 #
 resource "aws_eip" "nat_gw_eip" {
+  count = var.private_subnet_id == "" ? 1 : 0
   depends_on = [
-    aws_internet_gateway.internet_gw
+    aws_internet_gateway.internet_gw[0]
   ]
 }
 resource "aws_nat_gateway" "nat_gw" {
+  count = var.private_subnet_id == "" ? 1 : 0
   # A NAT gateway should be placed on a subnet with an internet gateway
-  subnet_id = aws_subnet.public_subnet.id
-  allocation_id = aws_eip.nat_gw_eip.id
+  subnet_id = aws_subnet.public_subnet[0].id
+  allocation_id = aws_eip.nat_gw_eip[0].id
 }
 resource "aws_route_table" "private_subnet_rt" {
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.private_subnet_id == "" ? 1 : 0
+  vpc_id = local.arvados_vpc_id
   route {
     cidr_block = "0.0.0.0/0"
-    nat_gateway_id = aws_nat_gateway.nat_gw.id
+    nat_gateway_id = aws_nat_gateway.nat_gw[0].id
   }
 }
 resource "aws_route_table_association" "private_subnet_assoc" {
-  subnet_id = aws_subnet.private_subnet.id
-  route_table_id = aws_route_table.private_subnet_rt.id
+  count = var.private_subnet_id == "" ? 1 : 0
+  subnet_id = aws_subnet.private_subnet[0].id
+  route_table_id = aws_route_table.private_subnet_rt[0].id
 }
 
 resource "aws_security_group" "arvados_sg" {
   name = "arvados_sg"
-  vpc_id = aws_vpc.arvados_vpc.id
+  count = var.sg_id == "" ? 1 : 0
+  vpc_id = aws_vpc.arvados_vpc[0].id
+
+  lifecycle {
+    precondition {
+      condition = (var.vpc_id == "")
+      error_message = "sg_id should be set if vpc_id is set"
+    }
+  }
 
   dynamic "ingress" {
     for_each = local.allowed_ports
@@ -116,7 +156,7 @@ resource "aws_security_group" "arvados_sg" {
     from_port = 0
     to_port = 0
     protocol = "-1"
-    cidr_blocks = [ aws_vpc.arvados_vpc.cidr_block ]
+    cidr_blocks = [ aws_vpc.arvados_vpc[0].cidr_block ]
   }
   # Even though AWS auto-creates an "allow all" egress rule,
   # Terraform deletes it, so we add it explicitly.
@@ -171,7 +211,7 @@ resource "aws_route53_record" "public_cname_record" {
 resource "aws_route53_zone" "private_zone" {
   name = var.domain_name
   vpc {
-    vpc_id = aws_vpc.arvados_vpc.id
+    vpc_id = local.arvados_vpc_id
   }
 }
 resource "aws_route53_record" "private_a_record" {
index e1c0fe171929e8faecc2550dcd0f45de9ac54253..ca11f5d0d87a760c1012c26ed9f64af5e0e32262 100644 (file)
@@ -3,22 +3,22 @@
 # SPDX-License-Identifier: CC-BY-SA-3.0
 
 output "arvados_vpc_id" {
-  value = aws_vpc.arvados_vpc.id
+  value = local.arvados_vpc_id
 }
 output "arvados_vpc_cidr" {
-  value = aws_vpc.arvados_vpc.cidr_block
+  value = try(local.arvados_vpc_cidr_block, "")
 }
 
 output "public_subnet_id" {
-  value = aws_subnet.public_subnet.id
+  value = local.public_subnet_id
 }
 
 output "private_subnet_id" {
-  value = aws_subnet.private_subnet.id
+  value = local.private_subnet_id
 }
 
 output "arvados_sg_id" {
-  value = aws_security_group.arvados_sg.id
+  value = local.arvados_sg_id
 }
 
 output "eip_id" {
index 9cc96437dc898d86913d4883693d6391b242be61..32480f879a3325092e32f711917abe11a3de8e89 100644 (file)
@@ -7,4 +7,12 @@ region_name = "us-east-1"
 # domain_name = "xarv1.example.com"
 
 # Uncomment this to create an non-publicly accessible Arvados cluster
-# private_only = true
\ No newline at end of file
+# private_only = true
+
+# Optional networking options. Set existing resources to be used instead of
+# creating new ones.
+# NOTE: We only support fully managed or fully custom networking, not a mix of both.
+# vpc_id = "vpc-"
+# sg_id = "sg-"
+# public_subnet_id = "subnet-"
+# private_subnet_id = "subnet-"
\ No newline at end of file
index 276f31433499faee401580630b6a9343ced8e633..e14c5980852166103c3d453477d82b256d311255 100644 (file)
@@ -37,4 +37,28 @@ variable "internal_service_hosts" {
   description = "List of hostnames for nodes that hold internal Arvados services"
   type = list(string)
   default = [ "keep0", "shell" ]
+}
+
+variable "vpc_id" {
+  description = "Use existing VPC instead of creating one for the cluster"
+  type = string
+  default = ""
+}
+
+variable "sg_id" {
+  description = "Use existing security group instead of creating one for the cluster"
+  type = string
+  default = ""
+}
+
+variable "private_subnet_id" {
+  description = "Use existing private subnet instead of creating one for the cluster"
+  type = string
+  default = ""
+}
+
+variable "public_subnet_id" {
+  description = "Use existing public subnet instead of creating one for the cluster"
+  type = string
+  default = ""
 }
\ No newline at end of file