From b8715101d8e6d10e1da91e4bb02f17d62f2f2dc9 Mon Sep 17 00:00:00 2001 From: ITQ Date: Wed, 6 Aug 2025 03:09:06 +0300 Subject: [PATCH] feat: added main terraform module --- terraform/locals.tf | 39 +++++++++++++++++++++++ terraform/main.tf | 70 ++++++++++++++++++++++++++++++++++++++++++ terraform/provider.tf | 11 +++++++ terraform/variables.tf | 66 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 terraform/locals.tf create mode 100644 terraform/main.tf create mode 100644 terraform/provider.tf create mode 100644 terraform/variables.tf diff --git a/terraform/locals.tf b/terraform/locals.tf new file mode 100644 index 0000000..5a678a4 --- /dev/null +++ b/terraform/locals.tf @@ -0,0 +1,39 @@ +locals { + dot_env_file_path = ".env" + dot_env_regex = "(?m:^\\s*([^#\\s]\\S*)\\s*=\\s*[\"']?(.*[^\"'\\s])[\"']?\\s*$)" + dot_env = { for tuple in regexall(local.dot_env_regex, file(local.dot_env_file_path)) : tuple[0] => sensitive(tuple[1]) } + + uri = local.dot_env["LIBVIRT_DEFAULT_URI"] + + cidrs = [ + var.network_ipv4_cidr, + var.network_ipv6_cidr, + ] + image_source = "${var.image_pool_folder}/${var.image_filename}" + user_templates = merge( + { control_plane = "control-plane.yaml.tpl" }, + { for ip in var.worker_ipv4s : "worker_${replace(ip, "\\.", "-")}" => "worker.yaml.tpl" } + ) + + ipv4_prefix = tonumber(split("/", var.network_ipv4_cidr)[1]) + ipv4_gateway = cidrhost(var.network_ipv4_cidr, 1) + ipv6_prefix = tonumber(split("/", var.network_ipv6_cidr)[1]) + ipv6_gateway = cidrhost(var.network_ipv6_cidr, 1) + + node_addrs = merge( + { control_plane = { ipv4 = var.control_plane_ipv4, ipv6 = var.control_plane_ipv6 } }, + { for idx, ip in var.worker_ipv4s : + "worker_${replace(ip, "\\.", "-")}" => { ipv4 = ip, ipv6 = var.worker_ipv6s[idx] } + } + ) + + nodes = { for key, addr in local.node_addrs : + key => { + ipv4 = addr.ipv4 + ipv6 = addr.ipv6 + image = contains(keys(libvirt_volume.worker_images), key) ? libvirt_volume.worker_images[key].id : libvirt_volume.control_plane_image.id + user_data = data.template_file.user_data[key].rendered + network_config = data.template_file.network_config[key].rendered + } + } +} diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..2a39201 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,70 @@ +resource "libvirt_network" "default" { + name = "${var.naming_prefix}default" + mode = "nat" + addresses = local.cidrs + mtu = var.mtu + autostart = true + + dns { + local_only = false + + forwarders { + address = "1.1.1.1" + } + } +} + +resource "libvirt_volume" "base" { + name = "${var.naming_prefix}ubuntu_noble" + source = local.image_source +} + +resource "libvirt_volume" "control_plane_image" { + name = "${var.naming_prefix}control_plane_image" + base_volume_id = libvirt_volume.base.id +} + +resource "libvirt_volume" "worker_images" { + for_each = { for ip in var.worker_ipv4s : "worker_${replace(ip, "\\.", "-")}" => ip } + name = "${var.naming_prefix}${each.key}_image" + base_volume_id = libvirt_volume.base.id +} + +data "template_file" "user_data" { + for_each = local.user_templates + + template = file("${path.module}/configs/cloud-init/${each.value}") + vars = { + hosts_file = base64encode(file("${path.module}/configs/hosts")) + ssh_public_key = file("../.ssh/id_rsa.pub") + } +} + +data "template_file" "network_config" { + for_each = local.user_templates + + template = file("${path.module}/configs/cloud-init/network.yaml.tpl") + vars = { + ipv4_address = local.node_addrs[each.key].ipv4 + ipv4_prefix = local.ipv4_prefix + ipv4_gateway = local.ipv4_gateway + ipv6_address = local.node_addrs[each.key].ipv6 + ipv6_prefix = local.ipv6_prefix + ipv6_gateway = local.ipv6_gateway + } +} + +module "nodes" { + source = "./modules/instance" + for_each = local.nodes + + name = each.key + network_id = libvirt_network.default.id + ipv4 = each.value.ipv4 + ipv6 = each.value.ipv6 + volume_base_id = each.value.image + user_data = each.value.user_data + network_config = each.value.network_config + vcpu = var.cpu_per_node + memory = var.mem_per_node +} diff --git a/terraform/provider.tf b/terraform/provider.tf new file mode 100644 index 0000000..88c8416 --- /dev/null +++ b/terraform/provider.tf @@ -0,0 +1,11 @@ +terraform { + required_providers { + libvirt = { + source = "dmacvicar/libvirt" + } + } +} + +provider "libvirt" { + uri = local.uri +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..bcb9b37 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,66 @@ +variable "naming_prefix" { + type = string + default = "task13_" +} + +variable "dot_env_file_path" { + type = string + default = ".env" +} + +variable "image_pool_folder" { + description = "Local folder where base images are stored" + type = string + default = "../assets/images" +} + +variable "image_filename" { + description = "Name of the base cloud image file" + type = string + default = "noble-server-cloudimg-amd64.img" +} + +variable "control_plane_ipv4" { + type = string + default = "10.6.6.10" +} + +variable "control_plane_ipv6" { + type = string + default = "2001:db8:ca2:2::10" +} + +variable "worker_ipv4s" { + type = list(string) + default = ["10.6.6.20"] +} + +variable "worker_ipv6s" { + type = list(string) + default = ["2001:db8:ca2:2::20"] +} + +variable "network_ipv4_cidr" { + type = string + default = "10.6.6.0/24" +} + +variable "network_ipv6_cidr" { + type = string + default = "2001:db8:ca2:2::/64" +} + +variable "mtu" { + type = number + default = 1500 +} + +variable "cpu_per_node" { + type = number + default = 4 +} + +variable "mem_per_node" { + type = number + default = 2048 +}