diff --git a/openstack-tf/d4s-dev/ckan-catalogue-engines/main.tf b/openstack-tf/d4s-dev/ckan-catalogue-engines/main.tf new file mode 100644 index 0000000..b1068ab --- /dev/null +++ b/openstack-tf/d4s-dev/ckan-catalogue-engines/main.tf @@ -0,0 +1,103 @@ +# Define required providers +terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = ">= 1.54.0" + } + } +} + +data "terraform_remote_state" "privnet_dns_router" { + backend = "local" + + config = { + path = "../project-setup/terraform.tfstate" + } +} + +# +# Uses common_variables as module +# +module "common_variables" { + source = "../../modules/common_variables" +} + +# Module used +module "ssh_settings" { + source = "../../modules/ssh-key-ref" +} + + +# +# Creates the server group "ckan-catalogue", NB but I'm not using it!!!! +# +resource "openstack_compute_servergroup_v2" "ckan-catalogue" { + name = "ckan-catalogue" + policies = [module.common_variables.policy_list.soft_anti_affinity] +} + + +# +# Postgres instances via "postgres" module +# +module "instance_postgres_via_module" { + source = "../../modules/postgres" + + # Postgres networking configuration. + # NB. use this configuration by settings properly all the key fields + # postgres_networking_data = { + # description = "Data for the PostgreSQL server, including network CIDR and server IP" + # networking_security_group_name = "my network security name" + # network_cidr = "192.168.0.0/22" + # server_ip = "192.168.0.5" + # network_name = "the_network_name" + # server_cidr = "192.168.0.5/22" + # port_range_min = 5432 + # port_range_max = 5432 + # } + + # Postgres instance + postgres_instance_data = { + postgres-ckan-dev = { + name = "postgres-ckan-dev", + description = "The Postgres ckan-dev instance", + flavor = module.common_variables.flavor_list.m1_large, + networks = [data.terraform_remote_state.privnet_dns_router.outputs.main_private_network.name, module.common_variables.networks_list.shared_postgresql], + security_groups = [data.terraform_remote_state.privnet_dns_router.outputs.default_security_group_name, data.terraform_remote_state.privnet_dns_router.outputs.security_group_list.http_and_https_from_the_load_balancers], + server_groups_ids = [], + image_ref = module.common_variables.ubuntu_2204, + volume = { + name = "postgres-ckan-dev_data_volume", + size = "20", + device = "/dev/vdb", + } + } + } +} + + +# +# Solr instances via "instance_with_data_volume" module +# +module "instance_with_data_volume" { + source = "../../modules/instance_with_data_volume" + + instances_with_data_volume_map = { + solr-ckan-dev = { + name = "solr-ckan-dev", + description = "The Solr ckan-dev instance", + flavor = module.common_variables.flavor_list.m1_large, + networks = [data.terraform_remote_state.privnet_dns_router.outputs.main_private_network.name], + security_groups = [data.terraform_remote_state.privnet_dns_router.outputs.default_security_group_name, data.terraform_remote_state.privnet_dns_router.outputs.security_group_list.http_and_https_from_the_load_balancers], + server_groups_ids = [], + image_ref = module.common_variables.ubuntu_2204, + volume = { + name = "solr-ckan-dev_data_volume", + size = "20", + device = "/dev/vdb" + } + } + } +} diff --git a/openstack-tf/d4s-dev/ckan-catalogue-engines/provider.tf b/openstack-tf/d4s-dev/ckan-catalogue-engines/provider.tf new file mode 100644 index 0000000..fa7a121 --- /dev/null +++ b/openstack-tf/d4s-dev/ckan-catalogue-engines/provider.tf @@ -0,0 +1,3 @@ +provider "openstack" { + cloud = "d4s-dev" +} diff --git a/openstack-tf/d4s-dev/ckan-catalogue-engines/variables_ckan_instances.tf b/openstack-tf/d4s-dev/ckan-catalogue-engines/variables_ckan_instances.tf new file mode 100644 index 0000000..66f1503 --- /dev/null +++ b/openstack-tf/d4s-dev/ckan-catalogue-engines/variables_ckan_instances.tf @@ -0,0 +1,6 @@ + +# Default instances without data volume is EMPTY. Override it to create a proper instance plan +variable "ckan_instances" { + type = list(string) + default = ["ckan-dev"] +} diff --git a/openstack-tf/modules/postgres/main.tf b/openstack-tf/modules/postgres/main.tf new file mode 100644 index 0000000..eadf73b --- /dev/null +++ b/openstack-tf/modules/postgres/main.tf @@ -0,0 +1,139 @@ +#################################################################################################################################################################### +# +# Optional configuration for networking on Postgres +# +#################################################################################################################################################################### + +# Security group for ingress to PostgreSQL +resource "openstack_networking_secgroup_v2" "postgresql_networking_ingress" { + count = length(var.postgres_networking_data["networking_security_group_name"]) > 0 ? 1 : 0 + + name = "${var.postgres_networking_data["networking_security_group_name"]}_ingress" + delete_default_rules = true + description = "Access to the PostgreSQL service using the dedicated network" +} + +# Ingress rule for PostgreSQL +resource "openstack_networking_secgroup_rule_v2" "postgresql_ingress_rule" { + count = length(var.postgres_networking_data["networking_security_group_name"]) > 0 ? 1 : 0 + + security_group_id = openstack_networking_secgroup_v2.postgresql_networking_ingress[0].id + description = "Allow connections to port ranges ${var.postgres_networking_data["port_range_min"]} / ${var.postgres_networking_data["port_range_max"]} from the dedicated ${var.postgres_networking_data["network_cidr"]} network" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = var.postgres_networking_data["port_range_min"] + port_range_max = var.postgres_networking_data["port_range_max"] + remote_ip_prefix = var.postgres_networking_data["network_cidr"] +} + +# Security group for egress from VM to PostgreSQL server +resource "openstack_networking_secgroup_v2" "postgresql_egress" { + count = length(var.postgres_networking_data["networking_security_group_name"]) > 0 ? 1 : 0 + + name = "${var.postgres_networking_data["networking_security_group_name"]}_egress" + delete_default_rules = true + description = "Access to the shared PostgreSQL service from the VM port in the dedicated network" +} + +# Egress rule for PostgreSQL (TCP) +resource "openstack_networking_secgroup_rule_v2" "postgresql_egress_rule_tcp" { + count = length(var.postgres_networking_data["networking_security_group_name"]) > 0 ? 1 : 0 + + security_group_id = openstack_networking_secgroup_v2.postgresql_egress[0].id + description = "Allow egress connections to port/s on the PostgreSQL server" + direction = "egress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = var.postgres_networking_data["port_range_min"] + port_range_max = var.postgres_networking_data["port_range_max"] + remote_ip_prefix = var.postgres_networking_data["server_cidr"] +} + +# Egress rule for PostgreSQL (ICMP) +resource "openstack_networking_secgroup_rule_v2" "postgresql_egress_rule_icmp" { + for_each = length(var.postgres_networking_data["networking_security_group_name"]) > 0 ? { "egress_icmp_rule" : var.postgres_networking_data } : {} + + security_group_id = openstack_networking_secgroup_v2.postgresql_egress[0].id + description = "Allow ICMP traffic to the PostgreSQL server" + direction = "egress" + ethertype = "IPv4" + protocol = "icmp" + remote_ip_prefix = var.postgres_networking_data["server_cidr"] +} + +#################################################################################################################################################################### +# +# Posgres instance configuration +# +#################################################################################################################################################################### + +#Instance volume +resource "openstack_blockstorage_volume_v3" "instance_data_volume" { + for_each = var.postgres_instance_data + name = each.value.volume.name + size = each.value.volume.size +} + +# Generic postgres_service instance +resource "openstack_compute_instance_v2" "postgres_service" { + for_each = var.postgres_instance_data + name = each.value.name + availability_zone_hints = module.common_variables.availability_zone_no_gpu_name + flavor_name = each.value.flavor + key_pair = module.ssh_settings.ssh_key_name + security_groups = each.value.security_groups + block_device { + uuid = each.value.image_ref.uuid + source_type = "image" + volume_size = each.value.image_volume_size + boot_index = 0 + destination_type = "volume" + delete_on_termination = false + } + + # Creates the networks according to input networks + dynamic "network" { + for_each = each.value.networks + content { + name = network.value + } + } + + # Creates the networks according to input networks + dynamic "network" { + for_each = length(var.postgres_networking_data["server_ip"]) > 0 ? { "server_ip" : var.postgres_networking_data["server_ip"] } : {} + content { + name = var.postgres_networking_data["network_name"] + fixed_ip_v4 = var.postgres_networking_data["server_ip"] + } + } + + # Creates the scheduler_hints (i.e. server groups) according to input server_groups_ids + dynamic "scheduler_hints" { + for_each = each.value.server_groups_ids + content { + group = scheduler_hints.value + } + } + + # user_data script used + user_data = file("${each.value.image_ref.user_data_file}") + # Do not replace the instance when the ssh key changes + lifecycle { + ignore_changes = [ + # Ignore changes to tags, e.g. because a management agent + # updates these based on some ruleset managed elsewhere. + key_pair, user_data, network + ] + } +} + +# Attach the additional volume +resource "openstack_compute_volume_attach_v2" "attach_volume" { + for_each = var.postgres_instance_data + instance_id = openstack_compute_instance_v2.postgres_service[each.key].id + volume_id = openstack_blockstorage_volume_v3.instance_data_volume[each.key].id + device = each.value.volume.device + depends_on = [openstack_compute_instance_v2.postgres_service] +} diff --git a/openstack-tf/modules/postgres/outputs.tf b/openstack-tf/modules/postgres/outputs.tf new file mode 100644 index 0000000..28a03b9 --- /dev/null +++ b/openstack-tf/modules/postgres/outputs.tf @@ -0,0 +1,8 @@ + +output "postgres_instance_data" { + value = var.postgres_instance_data +} + +output "postgres_networking_data" { + value = var.postgres_networking_data +} diff --git a/openstack-tf/modules/postgres/terraform-provider.tf b/openstack-tf/modules/postgres/terraform-provider.tf new file mode 100644 index 0000000..78f9022 --- /dev/null +++ b/openstack-tf/modules/postgres/terraform-provider.tf @@ -0,0 +1,21 @@ +# Define required providers +terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 1.54.0" + } + } +} + +# SSH settings +module "ssh_settings" { + source = "../../modules/ssh-key-ref" +} + +# Global variables (constants, really) +module "common_variables" { + source = "../../modules/common_variables" +} + diff --git a/openstack-tf/modules/postgres/variables_postgres.tf b/openstack-tf/modules/postgres/variables_postgres.tf new file mode 100644 index 0000000..a22c88e --- /dev/null +++ b/openstack-tf/modules/postgres/variables_postgres.tf @@ -0,0 +1,56 @@ + +# Variables.Override them to create a proper instance plan + +# Postgres instances +variable "postgres_instance_data" { + type = map(object({ + name = string + description = string + flavor = string + networks = list(string) + security_groups = list(string) + server_groups_ids = list(string) + image_ref = map(string) + image_volume_size = optional(number, 10) + volume = map(string) + })) + default = { + smartgears_service = { + name = "", + description = "", + flavor = "", + networks = [], + security_groups = [], + server_groups_ids = [], + image_ref = {}, + volume = {} + } + } + +} + +# Postgres networking configuration. +# NB. use this configuration by settings properly all the key fields +variable "postgres_networking_data" { + description = "Data for the PostgreSQL server, including network CIDR and server IP" + type = map(string) + # default = { + # networking_security_group_name = "my network security name" + # network_cidr = "192.168.0.0/22" + # server_ip = "192.168.0.5" + # network_name = "the_network_name" + # server_cidr = "192.168.0.5/22" + # port_range_min = 5432 + # port_range_max = 5432 + # } + + default = { + networking_security_group_name = "" + network_cidr = "" + server_ip = "" + network_name = "" + server_cidr = "" + port_range_min = "" + port_range_max = "" + } +}