From a58e77802b1f41f3c6123bb3d4b40347cb5252fa Mon Sep 17 00:00:00 2001 From: devsjc Date: Fri, 10 Nov 2023 13:14:05 +0000 Subject: [PATCH] Modify networking slightly --- terraform/india/development/backend.tf | 2 +- terraform/india/development/main.tf | 8 +- terraform/india/development/variables.tf | 5 + terraform/modules/networking/README.md | 11 +-- terraform/modules/networking/main.tf | 98 ++++++++++--------- terraform/modules/networking/output.tf | 8 +- terraform/modules/networking/variables.tf | 48 ++++++--- terraform/modules/services/api/eb.tf | 2 +- terraform/modules/services/api/variables.tf | 6 +- terraform/nowcasting/development/backend.tf | 37 +++++++ terraform/nowcasting/development/main.tf | 55 +++++------ terraform/nowcasting/development/provider.tf | 39 -------- terraform/nowcasting/development/variables.tf | 17 +--- 13 files changed, 179 insertions(+), 157 deletions(-) delete mode 100644 terraform/nowcasting/development/provider.tf diff --git a/terraform/india/development/backend.tf b/terraform/india/development/backend.tf index a9adbb8e..8c4b3835 100644 --- a/terraform/india/development/backend.tf +++ b/terraform/india/development/backend.tf @@ -29,7 +29,7 @@ provider "aws" { region = var.region default_tags { tags = { - environment = var.environment + environment = local.environment domain = local.domain } } diff --git a/terraform/india/development/main.tf b/terraform/india/development/main.tf index def64643..0be8f52e 100644 --- a/terraform/india/development/main.tf +++ b/terraform/india/development/main.tf @@ -1,16 +1,18 @@ locals { environment = "development" + domain = "india" } # Create the VPC, public and private subnets -module "networks" { +module "network" { source = "../../modules/networking" environment = local.environment + vpc_cidr = "10.1.0.0/16" } module "ecs_cluster" { source = "../../modules/ecs_cluster" environment = local.environment - region = module.networks.vpc_region - domain = "quartz" + region = module.network.vpc_region + domain = local.domain } \ No newline at end of file diff --git a/terraform/india/development/variables.tf b/terraform/india/development/variables.tf index e69de29b..fb357abf 100644 --- a/terraform/india/development/variables.tf +++ b/terraform/india/development/variables.tf @@ -0,0 +1,5 @@ +variable region { + type = string + default = "eu-west-1" + description = "AWS region" +} diff --git a/terraform/modules/networking/README.md b/terraform/modules/networking/README.md index ef9c73be..427594e3 100644 --- a/terraform/modules/networking/README.md +++ b/terraform/modules/networking/README.md @@ -1,9 +1,8 @@ # Modules/Networking This module makes - 1. VPC - 2. Elastic IP address - 3. NAT gateway - so things inside the VPC can reach the internet - 4. Subnets in the VPC. Both private and public - 5. Routing tables - 6. Security groups + 1. VPC with Elastic IP address and Internet Gateway + 2. Public and Private subnets + 3. NAT on the first Public Subnet + 4. Routing tables + 5. Security groups diff --git a/terraform/modules/networking/main.tf b/terraform/modules/networking/main.tf index 0eb94be2..baaf5b48 100644 --- a/terraform/modules/networking/main.tf +++ b/terraform/modules/networking/main.tf @@ -1,130 +1,139 @@ -# Creates lots of network things -# 1. VPC -# 2. Elastic IP address -# 3. NAT gateway - so things inside the VPC can reach the internet -# 4. Subnets in the VPC. Both private and public -# 5. Routing tables -# 6. Security groups +locals { + prefix = "${var.domain}-${var.environment}" + // Access the A.B part of the CIDR + ab = regex("^(\\d+.\\d+).", var.vpc_cidr) +} -/*==== The VPC ======*/ - +// VPC resource "aws_vpc" "vpc" { cidr_block = var.vpc_cidr enable_dns_hostnames = true enable_dns_support = true tags = { - name = "${var.environment}-vpc" + name = "${local.prefix}-vpc" } } -/* Internet gateway for the VPC */ +// Internet gateway for the VPC resource "aws_internet_gateway" "ig" { vpc_id = aws_vpc.vpc.id tags = { - name = "${var.environment}-igw" + name = "${local.prefix}-igw" } } -/* Elastic IP for NAT */ +// Elastic IP for the NAT resource "aws_eip" "nat_eip" { depends_on = [aws_internet_gateway.ig] } -/* NAT */ +// NAT gateway on first public subnet resource "aws_nat_gateway" "nat" { allocation_id = aws_eip.nat_eip.id - subnet_id = element(aws_subnet.public_subnet.*.id, 0) + subnet_id = aws_subnet.public_subnets[0].id depends_on = [aws_internet_gateway.ig] tags = { name = "nat" } } -/*==== Subnets ======*/ - -/* Public subnet */ - -resource "aws_subnet" "public_subnet" { +// Create the desired number of public subnets +resource "aws_subnet" "public_subnets" { vpc_id = aws_vpc.vpc.id - count = length(var.public_subnets_cidr) - cidr_block = element(var.public_subnets_cidr, count.index) + count = var.num_public_subnets + cidr_block = "${local.ab}.${count.index + 1}.0/24" availability_zone = element(var.availability_zones, count.index) map_public_ip_on_launch = true tags = { - name = "${var.environment}-${element(var.availability_zones, count.index)}-public-subnet" + name = "${local.prefix}-${element(var.availability_zones, count.index)}-public-subnet" } } -/* Private subnet */ +moved { + from = aws_subnet.public_subnet[0] + to = aws_subnet.public_subnets[0] +} -resource "aws_subnet" "private_subnet" { +// Create the desired number of private subnets +resource "aws_subnet" "private_subnets" { vpc_id = aws_vpc.vpc.id - count = length(var.private_subnets_cidr) - cidr_block = element(var.private_subnets_cidr, count.index) + count = var.num_private_subnets + cidr_block = "${local.ab}.${count.index + 20}.0/24" availability_zone = element(var.availability_zones, count.index) map_public_ip_on_launch = false tags = { - name = "${var.environment}-${element(var.availability_zones, count.index)}-private-subnet" + name = "${local.prefix}-${element(var.availability_zones, count.index)}-private-subnet" } } +moved { + from = aws_subnet.private_subnet[0] + to = aws_subnet.private_subnets[0] +} +moved { + from = aws_subnet.private_subnet[1] + to = aws_subnet.private_subnets[1] +} + +// Create a subnet group from the private subnets resource "aws_db_subnet_group" "private_subnet_group" { - name = "private-subnet-group-${var.environment}" + name = "${local.prefix}-private-subnet-group" description = "Terraform private subnet group" subnet_ids = [ - for subnet in aws_subnet.private_subnet : subnet.id + for subnet in aws_subnet.private_subnets : subnet.id ] } -/* Routing table for private subnet */ +// Rounting table for the private subnets resource "aws_route_table" "private" { vpc_id = aws_vpc.vpc.id tags = { - name = "${var.environment}-private-route-table" + name = "${local.prefix}-private-route-table" } } -/* Routing table for public subnet */ +// Routing table for the public subnets resource "aws_route_table" "public" { vpc_id = aws_vpc.vpc.id tags = { - name = "${var.environment}-public-route-table" + name = "${local.prefix}-public-route-table" } } +// Create routes to internet. +// * Public subnet -> internet gateway +// * Private subnet -> NAT gateway resource "aws_route" "public_internet_gateway" { route_table_id = aws_route_table.public.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.ig.id } - resource "aws_route" "private_nat_gateway" { route_table_id = aws_route_table.private.id destination_cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.nat.id } -/* Route table associations */ +// Add the routes to the route tables resource "aws_route_table_association" "public" { - for_each = aws_subnet.public_subnet - subnet_id = each.value.id + count = length(aws_subnet.public_subnets) + subnet_id = element(aws_subnet.public_subnets.*.id, count.index) route_table_id = aws_route_table.public.id } - resource "aws_route_table_association" "private" { - for_each = toset(aws_subnet.private_subnet) - subnet_id = each.value.id + count = length(aws_subnet.private_subnets) + subnet_id = element(aws_subnet.private_subnets.*.id, count.index) route_table_id = aws_route_table.private.id } -/*==== VPC's Default Security Group ======*/ - +// VPC default security group resource "aws_security_group" "default" { - name = "nowcasting-${var.environment}-default-sg" + name = "${local.prefix}-default-sg" description = "Default security group to allow inbound/outbound from the VPC" vpc_id = aws_vpc.vpc.id depends_on = [aws_vpc.vpc] + ingress { from_port = "0" to_port = "0" @@ -139,4 +148,3 @@ resource "aws_security_group" "default" { self = "true" } } - diff --git a/terraform/modules/networking/output.tf b/terraform/modules/networking/output.tf index 367f2121..872c7eed 100644 --- a/terraform/modules/networking/output.tf +++ b/terraform/modules/networking/output.tf @@ -4,7 +4,13 @@ output "vpc_id" { output "public_subnet_ids" { value = [ - for subnet in aws_subnet.public_subnet : subnet.id + for subnet in aws_subnet.public_subnets : subnet.id + ] +} + +output "private_subnet_ids" { + value = [ + for subnet in aws_subnet.private_subnets : subnet.id ] } diff --git a/terraform/modules/networking/variables.tf b/terraform/modules/networking/variables.tf index e1475ba9..23016117 100644 --- a/terraform/modules/networking/variables.tf +++ b/terraform/modules/networking/variables.tf @@ -1,3 +1,8 @@ +variable "region" { + description = "The AWS region" + default = "eu-west-1" +} + variable "environment" { description = "The Deployment environment" default = "development" @@ -11,23 +16,30 @@ variable "vpc_cidr" { type = string description = "The IPv4 CIDR block of the VPC. Use ranges from http://www.faqs.org/rfcs/rfc1918.html." default = "10.0.0.0/16" + validation { + condition = can(regex("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}\\/\\d+$", var.vpc_cidr)) + error_message = "Must be a valid IPv4 address of the form A.B.C.D/E." + } } -variable "public_subnets_cidr" { - type = list(string) - description = "List of IPv4 CIDR blocks for each desired public subnet. Defaults to one subnet." - default = ["10.0.1.0/24"] -} - -variable "private_subnets_cidr" { - type = list(string) - description = "List of IPv4 CIDR blocks for each desired private subnet. Defaults to two subnets." - default = ["10.0.20.0/24", "10.0.21.0/24"] +variable "num_public_subnets" { + type = number + description = "Number of public subnets to create in the VPC. Only the first will have a NAT." + default = 1 + validation { + condition = var.num_public_subnets < 4 + error_message = "Can't create more public subnets than availability zones." + } } -variable "region" { - description = "The AWS region" - default = "eu-west-1" +variable "num_private_subnets" { + type = number + description = "Number of private subnets to create in the VPC" + default = 2 + validation { + condition = var.num_private_subnets < 4 + error_message = "Can't create more private subnets than availability zones." + } } variable "availability_zones" { @@ -35,3 +47,13 @@ variable "availability_zones" { description = "The availability zones within the VPC where resources will be provisioned" default = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] } + +variable "domain" { + type = string + description = "The domain of the VPC" + default = "uk" + validation { + condition = contains(["uk", "india"], var.domain) + error_message = "Domain can only be one of 'uk' or 'india'." + } +} diff --git a/terraform/modules/services/api/eb.tf b/terraform/modules/services/api/eb.tf index 7067b0a6..a41ee3c5 100644 --- a/terraform/modules/services/api/eb.tf +++ b/terraform/modules/services/api/eb.tf @@ -111,7 +111,7 @@ resource "aws_elastic_beanstalk_environment" "eb-api-env" { name = "Subnets" # value = "${join(",", var.subnets)}" # value = var.subnets - value = var.subnet_ids[0] + value = var.subnet_id resource = "" } setting { diff --git a/terraform/modules/services/api/variables.tf b/terraform/modules/services/api/variables.tf index 30b99868..9583ef6f 100644 --- a/terraform/modules/services/api/variables.tf +++ b/terraform/modules/services/api/variables.tf @@ -13,9 +13,9 @@ variable "vpc_id" { } -variable "subnet_ids" { - description = "List of subnet ids where this application will run" - type = list(any) +variable "subnet_id" { + description = "Subnet id where this application will run" + type = string } # the type is any, as the subnets are terraform resources diff --git a/terraform/nowcasting/development/backend.tf b/terraform/nowcasting/development/backend.tf index d923ec52..d635084e 100644 --- a/terraform/nowcasting/development/backend.tf +++ b/terraform/nowcasting/development/backend.tf @@ -7,4 +7,41 @@ terraform { name = "nowcasting_infrastructure_development-eu-west-1" } } + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.47.0" + } + + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 3.9.1" + } + } + + required_version = ">= 0.14.9" +} + +provider "aws" { + region = var.region + default_tags { + tags = { + environment = local.environment + domain = local.domain + } + } +} + +variable "cloudflare_email" { + description = "Email Address of the Cloudflare account" +} + +variable "cloudflare_api_token" { + description = "API Token of the Cloudflare account" +} + +provider "cloudflare" { + email = var.cloudflare_email + api_token = var.cloudflare_api_token } diff --git a/terraform/nowcasting/development/main.tf b/terraform/nowcasting/development/main.tf index f065e4b5..1d345dbf 100644 --- a/terraform/nowcasting/development/main.tf +++ b/terraform/nowcasting/development/main.tf @@ -27,20 +27,13 @@ The componentes ares: Variables used across all modules ======*/ locals { - production_availability_zones = ["${var.region}a", "${var.region}b", "${var.region}c"] - domain = "nowcasting" + environment = "development" + domain = "uk" } # 0.1 module "networking" { source = "../../modules/networking" - - region = var.region - environment = var.environment - vpc_cidr = var.vpc_cidr - public_subnets_cidr = var.public_subnets_cidr - private_subnets_cidr = var.private_subnets_cidr - availability_zones = local.production_availability_zones } # 0.2 @@ -57,7 +50,7 @@ module "s3" { source = "../../modules/storage/s3-trio" region = var.region - environment = var.environment + environment = local.environment } # 0.4 @@ -65,7 +58,7 @@ module "ecs" { source = "../../modules/ecs_cluster" region = var.region - environment = var.environment + environment = local.environment domain = local.domain } @@ -74,7 +67,7 @@ module "forecasting_models_bucket" { source = "../../modules/storage/s3-private" region = var.region - environment = var.environment + environment = local.environment service_name = "national-forecaster-models" domain = local.domain lifecycled_prefixes = [] @@ -85,9 +78,9 @@ module "api" { source = "../../modules/services/api" region = var.region - environment = var.environment + environment = local.environment vpc_id = module.networking.vpc_id - subnet_ids = module.networking.public_subnet_ids[0] + subnet_id = module.networking.public_subnet_ids[0] docker_version = var.api_version database_forecast_secret_url = module.database.forecast-database-secret-url database_pv_secret_url = module.database.pv-database-secret-url @@ -105,7 +98,7 @@ module "database" { source = "../../modules/storage/database-pair" region = var.region - environment = var.environment + environment = local.environment db_subnet_group_name = module.networking.private_subnet_group_name vpc_id = module.networking.vpc_id } @@ -118,8 +111,8 @@ module "nwp" { ecs-task_type = "consumer" aws-region = var.region - aws-environment = var.environment - aws-secretsmanager_secret_name = "${var.environment}/data/nwp-consumer" + aws-environment = local.environment + aws-secretsmanager_secret_name = "${local.environment}/data/nwp-consumer" s3-buckets = [ { @@ -155,8 +148,8 @@ module "nwp-national" { ecs-task_type = "consumer" aws-region = var.region - aws-environment = var.environment - aws-secretsmanager_secret_name = "${var.environment}/data/nwp-consumer" + aws-environment = local.environment + aws-secretsmanager_secret_name = "${local.environment}/data/nwp-consumer" s3-buckets = [ { @@ -193,8 +186,8 @@ module "nwp-ecmwf" { ecs-task_type = "consumer" aws-region = var.region - aws-environment = var.environment - aws-secretsmanager_secret_name = "${var.environment}/data/nwp-consumer" + aws-environment = local.environment + aws-secretsmanager_secret_name = "${local.environment}/data/nwp-consumer" s3-buckets = [ { @@ -226,7 +219,7 @@ module "sat" { source = "../../modules/services/sat" region = var.region - environment = var.environment + environment = local.environment iam-policy-s3-sat-write = module.s3.iam-policy-s3-sat-write s3-bucket = module.s3.s3-sat-bucket ecs-cluster = module.ecs.ecs_cluster @@ -241,7 +234,7 @@ module "pv" { source = "../../modules/services/pv" region = var.region - environment = var.environment + environment = local.environment ecs-cluster = module.ecs.ecs_cluster public_subnet_ids = module.networking.public_subnet_ids database_secret = module.database.pv-database-secret @@ -257,7 +250,7 @@ module "gsp" { source = "../../modules/services/gsp" region = var.region - environment = var.environment + environment = local.environment ecs-cluster = module.ecs.ecs_cluster public_subnet_ids = module.networking.public_subnet_ids database_secret = module.database.forecast-database-secret @@ -270,7 +263,7 @@ module "metrics" { source = "../../modules/services/metrics" region = var.region - environment = var.environment + environment = local.environment ecs-cluster = module.ecs.ecs_cluster public_subnet_ids = module.networking.public_subnet_ids database_secret = module.database.forecast-database-secret @@ -284,7 +277,7 @@ module "forecast" { source = "../../modules/services/forecast" region = var.region - environment = var.environment + environment = local.environment ecs-cluster = module.ecs.ecs_cluster subnet_ids = module.networking.public_subnet_ids iam-policy-rds-read-secret = module.database.iam-policy-forecast-db-read @@ -305,7 +298,7 @@ module "national_forecast" { source = "../../modules/services/forecast_generic" region = var.region - environment = var.environment + environment = local.environment app-name = "forecast_national" ecs_config = { docker_image = "openclimatefix/gradboost_pv" @@ -338,7 +331,7 @@ module "forecast_pvnet" { source = "../../modules/services/forecast_generic" region = var.region - environment = var.environment + environment = local.environment app-name = "forecast_pvnet" ecs_config = { docker_image = "openclimatefix/pvnet_app" @@ -378,7 +371,7 @@ module "analysis_dashboard" { source = "../../modules/services/internal_ui" region = var.region - environment = var.environment + environment = local.environment eb_app_name = "internal-ui" domain = local.domain docker_config = { @@ -405,7 +398,7 @@ module "forecast_blend" { source = "../../modules/services/forecast_blend" region = var.region - environment = var.environment + environment = local.environment app-name = "forecast_blend" ecs_config = { docker_image = "openclimatefix/uk_pv_forecast_blend" @@ -425,7 +418,7 @@ module "forecast_blend" { module "airflow" { source = "../../modules/services/airflow" - environment = var.environment + environment = local.environment vpc_id = module.networking.vpc_id subnet_id = module.networking.public_subnet_ids[0] db_url = module.database.forecast-database-secret-airflow-url diff --git a/terraform/nowcasting/development/provider.tf b/terraform/nowcasting/development/provider.tf deleted file mode 100644 index 76d45d15..00000000 --- a/terraform/nowcasting/development/provider.tf +++ /dev/null @@ -1,39 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 4.47.0" - } - - cloudflare = { - source = "cloudflare/cloudflare" - version = "~> 3.9.1" - } - } - - required_version = ">= 0.14.9" -} - -provider "aws" { - region = var.region - default_tags { - tags = { - environment = var.environment - domain = local.domain - } - } -} - - -variable "cloudflare_email" { - description = "Email Address of the Cloudflare account" -} - -variable "cloudflare_api_token" { - description = "API Token of the Cloudflare account" -} - -provider "cloudflare" { - email = var.cloudflare_email - api_token = var.cloudflare_api_token -} diff --git a/terraform/nowcasting/development/variables.tf b/terraform/nowcasting/development/variables.tf index c0255310..6db5609d 100644 --- a/terraform/nowcasting/development/variables.tf +++ b/terraform/nowcasting/development/variables.tf @@ -1,24 +1,13 @@ variable "region" { description = "The AWS region to use" -} - -variable "environment" { - description = "The Deployment environment" + default = "eu-west-1" } //Networking variable "vpc_cidr" { description = "The CIDR block of the vpc" -} - -variable "public_subnets_cidr" { - type = list(string) - description = "The CIDR block for the public subnet" -} - -variable "private_subnets_cidr" { - type = list(string) - description = "The CIDR block for the private subnet" + type = string + default = "10.0.0.0/16" } variable "api_version" {