feat: initial commit
- have been working on this for some time now
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
resource "incus_image" "this" {
|
||||
source_image = {
|
||||
remote = var.remote
|
||||
name = var.name
|
||||
architecture = var.architecture
|
||||
aliases = var.aliases
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
output "fingerprint" {
|
||||
description = "The fingerprint of the pulled image."
|
||||
value = incus_image.this.fingerprint
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
variable "remote" {
|
||||
description = "The remote source of the image."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
description = "The name of the image to use."
|
||||
type = string
|
||||
}
|
||||
|
||||
|
||||
variable "architecture" {
|
||||
description = "The image architecture (e.g. x86_64, aarch64)."
|
||||
type = string
|
||||
default = "x86_64"
|
||||
}
|
||||
|
||||
variable "aliases" {
|
||||
description = "A list of aliases to assign to the image after pulling"
|
||||
type = list(string)
|
||||
default = null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "0.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
locals {
|
||||
netmask_to_prefix = {
|
||||
"0.0.0.0" = 0
|
||||
"128.0.0.0" = 1
|
||||
"192.0.0.0" = 2
|
||||
"224.0.0.0" = 3
|
||||
"240.0.0.0" = 4
|
||||
"248.0.0.0" = 5
|
||||
"252.0.0.0" = 6
|
||||
"254.0.0.0" = 7
|
||||
"255.0.0.0" = 8
|
||||
"255.128.0.0" = 9
|
||||
"255.192.0.0" = 10
|
||||
"255.224.0.0" = 11
|
||||
"255.240.0.0" = 12
|
||||
"255.248.0.0" = 13
|
||||
"255.252.0.0" = 14
|
||||
"255.254.0.0" = 15
|
||||
"255.255.0.0" = 16
|
||||
"255.255.128.0" = 17
|
||||
"255.255.192.0" = 18
|
||||
"255.255.224.0" = 19
|
||||
"255.255.240.0" = 20
|
||||
"255.255.248.0" = 21
|
||||
"255.255.252.0" = 22
|
||||
"255.255.254.0" = 23
|
||||
"255.255.255.0" = 24
|
||||
"255.255.255.128" = 25
|
||||
"255.255.255.192" = 26
|
||||
"255.255.255.224" = 27
|
||||
"255.255.255.240" = 28
|
||||
"255.255.255.248" = 29
|
||||
"255.255.255.252" = 30
|
||||
"255.255.255.254" = 31
|
||||
"255.255.255.255" = 32
|
||||
}
|
||||
prefix_length = lookup(local.netmask_to_prefix, var.cobbler_netmask, 24)
|
||||
host_bits = 32 - local.prefix_length
|
||||
total_hosts = pow(2, local.host_bits)
|
||||
last_usable_ip = local.total_hosts - 2
|
||||
|
||||
# derive subnet base from instance IP
|
||||
cidr_block = cidrsubnet("${incus_instance.this.ipv4_address}/${local.prefix_length}", 0, 0)
|
||||
|
||||
# get the last usable IP
|
||||
gateway_ip = cidrhost(local.cidr_block, local.last_usable_ip)
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
module "storage_volume" {
|
||||
source = "../../../../../../modules/storage_volume"
|
||||
|
||||
for_each = {
|
||||
for k, v in var.storage_volumes : "${var.name}-${k}" => v
|
||||
}
|
||||
|
||||
name = each.key
|
||||
pool = each.value.pool
|
||||
description = lookup(each.value, "description", null)
|
||||
type = lookup(each.value, "type", "custom")
|
||||
content_type = lookup(each.value, "content_type", null)
|
||||
config = lookup(each.value, "config", {})
|
||||
}
|
||||
|
||||
resource "incus_instance" "this" {
|
||||
name = var.name
|
||||
image = var.image
|
||||
description = var.description
|
||||
type = var.type
|
||||
ephemeral = var.ephemeral
|
||||
running = var.running
|
||||
profiles = var.profiles
|
||||
|
||||
dynamic "wait_for" {
|
||||
for_each = var.wait_for
|
||||
content {
|
||||
type = wait_for.value.type
|
||||
nic = wait_for.value.nic
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "device" {
|
||||
for_each = var.disk_devices
|
||||
content {
|
||||
name = device.value.name
|
||||
type = device.value.type
|
||||
properties = {
|
||||
path = device.value.properties["path"]
|
||||
source = device.value.properties["source"]
|
||||
pool = device.value.properties["pool"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "device" {
|
||||
for_each = {
|
||||
for k, v in var.storage_volumes : k => {
|
||||
name = k
|
||||
path = v.path
|
||||
pool = v.pool
|
||||
source = "${var.name}-${k}"
|
||||
}
|
||||
}
|
||||
content {
|
||||
name = device.value.name
|
||||
type = "disk"
|
||||
properties = {
|
||||
path = device.value.path
|
||||
source = device.value.source
|
||||
pool = device.value.pool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
module.storage_volume
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
resource "cobbler_system" "this" {
|
||||
name = "${var.name}.${var.cobbler_domain}"
|
||||
hostname = "${var.name}.${var.cobbler_domain}"
|
||||
profile = var.cobbler_profile
|
||||
status = "testing"
|
||||
name_servers = var.cobbler_name_servers
|
||||
mgmt_classes = var.cobbler_mgmt_classes
|
||||
name_servers_search = ["${var.cobbler_domain}"]
|
||||
|
||||
interface {
|
||||
name = "eth0"
|
||||
mac_address = incus_instance.this.mac_address
|
||||
static = true
|
||||
ip_address = incus_instance.this.ipv4_address
|
||||
netmask = var.cobbler_netmask
|
||||
dns_name = "${var.name}.${var.cobbler_domain}"
|
||||
gateway = local.gateway_ip
|
||||
}
|
||||
|
||||
depends_on = [incus_instance.this]
|
||||
}
|
||||
|
||||
resource "puppetdb_node" "this" {
|
||||
certname = "${var.name}.${var.cobbler_domain}"
|
||||
|
||||
depends_on = [incus_instance.this]
|
||||
}
|
||||
|
||||
resource "null_resource" "wait_for_instance_ready" {
|
||||
depends_on = [incus_instance.this]
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = "sleep 10"
|
||||
}
|
||||
}
|
||||
|
||||
resource "puppetca_certificate" "cert" {
|
||||
name = "${var.name}.${var.cobbler_domain}"
|
||||
env = "production"
|
||||
sign = false
|
||||
|
||||
depends_on = [
|
||||
null_resource.wait_for_instance_ready
|
||||
]
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = false
|
||||
}
|
||||
}
|
||||
|
||||
#resource "puppetca_certificate" "cert" {
|
||||
# count = (
|
||||
# var.check_on_instance_creation ? 1 :
|
||||
# (
|
||||
# can(incus_instance.this.ipv4_address) && incus_instance.this.ipv4_address != "" ? 1 : 0
|
||||
# )
|
||||
# )
|
||||
#
|
||||
# name = "${var.name}.${var.cobbler_domain}"
|
||||
# env = "production"
|
||||
# sign = false
|
||||
#
|
||||
# depends_on = [incus_instance.this]
|
||||
#
|
||||
# lifecycle {
|
||||
# create_before_destroy = false
|
||||
# }
|
||||
#}
|
||||
@@ -0,0 +1,12 @@
|
||||
#output "vm_metadata" {
|
||||
# value = {
|
||||
# ipaddress = incus_instance.this.ipv4_address
|
||||
# gateway = local.gateway_ip
|
||||
# hostname = "${var.name}.${var.cobbler_domain}"
|
||||
# interface = "eth0"
|
||||
# }
|
||||
#}
|
||||
|
||||
output "hostname" {
|
||||
value = "${var.name}.${var.cobbler_domain}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
provider "cobbler" {
|
||||
username = var.cobbler_username
|
||||
password = var.cobbler_password
|
||||
url = var.cobbler_url
|
||||
}
|
||||
|
||||
provider "puppetdb" {
|
||||
url = var.puppetdb_url
|
||||
ca = var.puppet_cert_ca
|
||||
cert = var.puppet_cert_pub
|
||||
key = var.puppet_cert_priv
|
||||
}
|
||||
|
||||
provider "puppetca" {
|
||||
url = var.puppetca_url
|
||||
ca = var.puppet_cert_ca
|
||||
cert = var.puppet_cert_pub
|
||||
key = var.puppet_cert_priv
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
variable "name" {
|
||||
description = "Name of the instance."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
description = "Base image from which the instance will be created."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
description = "Description of the instance."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "type" {
|
||||
description = "Instance type. Can be 'container' or 'virtual-machine'."
|
||||
type = string
|
||||
default = "container"
|
||||
}
|
||||
|
||||
variable "ephemeral" {
|
||||
description = "Whether this instance is ephemeral."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "running" {
|
||||
description = "Whether the instance should be started (running)."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "wait_for" {
|
||||
description = <<EOT
|
||||
List of wait_for blocks. Each block should contain:
|
||||
- type: Type of wait (e.g., ipv4, ipv6)
|
||||
- nic: Network interface name (e.g., eth0)
|
||||
EOT
|
||||
type = list(object({
|
||||
type = string
|
||||
nic = string
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "profiles" {
|
||||
description = "List of Incus config profiles to apply to the instance. Use [] to apply none."
|
||||
type = list(string)
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "disk_devices" {
|
||||
description = <<EOT
|
||||
List of disk devices to attach to the instance. Each device must be:
|
||||
- name : Name of the device
|
||||
- type : Must be "disk"
|
||||
- properties : Must include at least 'path', 'source', and 'pool'
|
||||
EOT
|
||||
|
||||
type = list(object({
|
||||
name = string
|
||||
type = string
|
||||
properties = object({
|
||||
path = string
|
||||
source = string
|
||||
pool = string
|
||||
})
|
||||
}))
|
||||
|
||||
default = []
|
||||
|
||||
validation {
|
||||
condition = alltrue([for d in var.disk_devices : d.type == "disk"])
|
||||
error_message = "All devices must have type 'disk'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "storage_volumes" {
|
||||
description = "Map of storage volumes to create and attach."
|
||||
type = map(object({
|
||||
pool = string
|
||||
description = optional(string)
|
||||
type = optional(string)
|
||||
content_type = optional(string)
|
||||
config = optional(map(string))
|
||||
path = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "cobbler_domain" {
|
||||
description = "Domain to assign in Cobbler for the system hostname"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_profile" {
|
||||
description = "Cobbler OS profile to use"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_netmask" {
|
||||
description = "Cobbler eth0 netmask to use"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_name_servers" {
|
||||
description = "List of name servers for the Cobbler system"
|
||||
type = list(string)
|
||||
default = ["198.18.13.12", "198.18.13.13"]
|
||||
}
|
||||
|
||||
variable "cobbler_mgmt_classes" {
|
||||
description = "List of Cobbler management classes. Must contain exactly 1 item."
|
||||
type = list(string)
|
||||
default = ["roles::base"]
|
||||
|
||||
validation {
|
||||
condition = length(var.cobbler_mgmt_classes) == 1
|
||||
error_message = "You must provide exactly 1 Cobbler management class."
|
||||
}
|
||||
}
|
||||
|
||||
variable "cobbler_url" {
|
||||
description = "The URL to the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_username" {
|
||||
description = "The username for the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_password" {
|
||||
description = "The password for the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_ca" {
|
||||
description = "Puppet CA cert content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_pub" {
|
||||
description = "PuppetDB client cert content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_priv" {
|
||||
description = "PuppetDB client private key content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppetdb_url" {
|
||||
description = "The URL of the PuppetPB API"
|
||||
type = string
|
||||
default = "https://puppetdbapi.query.consul:8081"
|
||||
}
|
||||
|
||||
variable "puppetca_url" {
|
||||
description = "The URL of the Puppet Certificate Authority (CA) server"
|
||||
type = string
|
||||
default = "https://puppetca.query.consul:8140"
|
||||
}
|
||||
|
||||
variable "check_on_instance_creation" {
|
||||
description = "If false, defer puppetca_certificate creation until instance is fully created."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
provider "cobbler" {
|
||||
username = var.cobbler_username
|
||||
password = var.cobbler_password
|
||||
url = var.cobbler_url
|
||||
}
|
||||
|
||||
provider "puppetdb" {
|
||||
url = var.puppetdb_url
|
||||
ca = var.puppet_cert_ca
|
||||
cert = var.puppet_cert_pub
|
||||
key = var.puppet_cert_priv
|
||||
}
|
||||
|
||||
provider "puppetca" {
|
||||
url = var.puppetca_url
|
||||
ca = var.puppet_cert_ca
|
||||
cert = var.puppet_cert_pub
|
||||
key = var.puppet_cert_priv
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
variable "name" {
|
||||
description = "Name of the instance."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
description = "Base image from which the instance will be created."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
description = "Description of the instance."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "type" {
|
||||
description = "Instance type. Can be 'container' or 'virtual-machine'."
|
||||
type = string
|
||||
default = "container"
|
||||
}
|
||||
|
||||
variable "ephemeral" {
|
||||
description = "Whether this instance is ephemeral."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "running" {
|
||||
description = "Whether the instance should be started (running)."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "wait_for" {
|
||||
description = <<EOT
|
||||
List of wait_for blocks. Each block should contain:
|
||||
- type: Type of wait (e.g., ipv4, ipv6)
|
||||
- nic: Network interface name (e.g., eth0)
|
||||
EOT
|
||||
type = list(object({
|
||||
type = string
|
||||
nic = string
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "profiles" {
|
||||
description = "List of Incus config profiles to apply to the instance. Use [] to apply none."
|
||||
type = list(string)
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "disk_devices" {
|
||||
description = <<EOT
|
||||
List of disk devices to attach to the instance. Each device must be:
|
||||
- name : Name of the device
|
||||
- type : Must be "disk"
|
||||
- properties : Must include at least 'path', 'source', and 'pool'
|
||||
EOT
|
||||
|
||||
type = list(object({
|
||||
name = string
|
||||
type = string
|
||||
properties = object({
|
||||
path = string
|
||||
source = string
|
||||
pool = string
|
||||
})
|
||||
}))
|
||||
|
||||
default = []
|
||||
|
||||
validation {
|
||||
condition = alltrue([for d in var.disk_devices : d.type == "disk"])
|
||||
error_message = "All devices must have type 'disk'."
|
||||
}
|
||||
}
|
||||
|
||||
variable "storage_volumes" {
|
||||
description = "Map of storage volumes to create and attach."
|
||||
type = map(object({
|
||||
pool = string
|
||||
description = optional(string)
|
||||
type = optional(string)
|
||||
content_type = optional(string)
|
||||
config = optional(map(string))
|
||||
path = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "cobbler_domain" {
|
||||
description = "Domain to assign in Cobbler for the system hostname"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_profile" {
|
||||
description = "Cobbler OS profile to use"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_netmask" {
|
||||
description = "Cobbler eth0 netmask to use"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_name_servers" {
|
||||
description = "List of name servers for the Cobbler system"
|
||||
type = list(string)
|
||||
default = ["198.18.13.12", "198.18.13.13"]
|
||||
}
|
||||
|
||||
variable "cobbler_mgmt_classes" {
|
||||
description = "List of Cobbler management classes. Must contain exactly 1 item."
|
||||
type = list(string)
|
||||
default = ["roles::base"]
|
||||
|
||||
validation {
|
||||
condition = length(var.cobbler_mgmt_classes) == 1
|
||||
error_message = "You must provide exactly 1 Cobbler management class."
|
||||
}
|
||||
}
|
||||
|
||||
variable "cobbler_url" {
|
||||
description = "The URL to the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_username" {
|
||||
description = "The username for the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cobbler_password" {
|
||||
description = "The password for the Cobbler API"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_ca" {
|
||||
description = "Puppet CA cert content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_pub" {
|
||||
description = "PuppetDB client cert content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppet_cert_priv" {
|
||||
description = "PuppetDB client private key content"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "puppetdb_url" {
|
||||
description = "The URL of the PuppetPB API"
|
||||
type = string
|
||||
default = "https://puppetdbapi.query.consul:8081"
|
||||
}
|
||||
|
||||
variable "puppetca_url" {
|
||||
description = "The URL of the Puppet Certificate Authority (CA) server"
|
||||
type = string
|
||||
default = "https://puppetca.query.consul:8140"
|
||||
}
|
||||
|
||||
variable "check_on_instance_creation" {
|
||||
description = "If false, defer puppetca_certificate creation until instance is fully created."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
resource "incus_network" "this" {
|
||||
name = var.name
|
||||
type = var.type
|
||||
config = var.config
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
variable "name" {
|
||||
type = string
|
||||
description = "The name of the network to define"
|
||||
}
|
||||
|
||||
variable "type" {
|
||||
description = <<EOT
|
||||
(Optional) The type of network to create.
|
||||
Can be one of: bridge, macvlan, sriov, ovn, or physical.
|
||||
If no type is specified, a bridge network is created.
|
||||
EOT
|
||||
|
||||
type = string
|
||||
default = "bridge"
|
||||
validation {
|
||||
condition = contains(["bridge", "macvlan", "sriov", "ovn", "physical"], var.type)
|
||||
error_message = "Type must be one of: bridge, macvlan, sriov, ovn, or physical."
|
||||
}
|
||||
}
|
||||
|
||||
variable "config" {
|
||||
description = "(Optional) Map of key/value pairs of network config settings."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "0.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
module "image" {
|
||||
source = "../../../../../../modules/image"
|
||||
|
||||
for_each = var.images
|
||||
|
||||
name = each.key
|
||||
remote = lookup(each.value, "remote")
|
||||
architecture = lookup(each.value, "architecture", null)
|
||||
}
|
||||
|
||||
module "network" {
|
||||
source = "../../../../../../modules/network"
|
||||
|
||||
for_each = var.networks
|
||||
|
||||
name = each.key
|
||||
type = lookup(each.value, "type")
|
||||
config = lookup(each.value, "config", {})
|
||||
}
|
||||
|
||||
module "profile" {
|
||||
source = "../../../../../../modules/profile"
|
||||
|
||||
for_each = var.profiles
|
||||
|
||||
name = each.key
|
||||
description = lookup(each.value, "description", null)
|
||||
project = lookup(each.value, "project", null)
|
||||
config = lookup(each.value, "config", {})
|
||||
devices = lookup(each.value, "devices", [])
|
||||
}
|
||||
|
||||
module "storage_pool" {
|
||||
source = "../../../../../../modules/storage_pool"
|
||||
|
||||
for_each = var.storage_pools
|
||||
|
||||
name = each.key
|
||||
description = lookup(each.value, "description", null)
|
||||
project = lookup(each.value, "project", null)
|
||||
driver = lookup(each.value, "driver")
|
||||
config = lookup(each.value, "config", {})
|
||||
}
|
||||
|
||||
module "storage_volume" {
|
||||
source = "../../../../../../modules/storage_volume"
|
||||
|
||||
for_each = var.storage_volumes
|
||||
|
||||
name = each.key
|
||||
pool = each.value.pool
|
||||
description = lookup(each.value, "description", null)
|
||||
type = lookup(each.value, "type", "custom")
|
||||
content_type = lookup(each.value, "content_type", null)
|
||||
config = lookup(each.value, "config", {})
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
variable "node_name" {
|
||||
type = string
|
||||
description = "Name of the node. This is used to fetch the corresponding token from Vault."
|
||||
}
|
||||
|
||||
variable "node_addr" {
|
||||
type = string
|
||||
description = "The address of the Incus node."
|
||||
}
|
||||
|
||||
variable "node_port" {
|
||||
type = string
|
||||
description = "The port Incus is listening on."
|
||||
default = "8443"
|
||||
}
|
||||
|
||||
variable "images" {
|
||||
description = "A map of images to be imported on this host"
|
||||
type = map(object({
|
||||
remote = string
|
||||
architecture = optional(string)
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "networks" {
|
||||
description = "A map of networks to be imported on this host"
|
||||
type = map(object({
|
||||
type = string
|
||||
config = optional(map(string))
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "profiles" {
|
||||
description = "A map of profiles to be imported on this host"
|
||||
type = map(object({
|
||||
description = optional(string, null)
|
||||
project = optional(string, null)
|
||||
config = optional(map(string), {})
|
||||
devices = optional(list(object({
|
||||
name = string
|
||||
type = string
|
||||
properties = optional(map(string))
|
||||
network = optional(string)
|
||||
})), [])
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "storage_pools" {
|
||||
description = "A map of storage pools to be created on this host"
|
||||
type = map(object({
|
||||
driver = string # Required
|
||||
description = optional(string, null) # Optional
|
||||
project = optional(string, null) # Optional
|
||||
config = optional(map(string), {}) # Optional
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "storage_volumes" {
|
||||
description = "A map of storage volumes to be created on this host"
|
||||
type = map(object({
|
||||
pool = string # Required
|
||||
description = optional(string, null) # Optional
|
||||
type = optional(string, "custom") # Optional
|
||||
content_type = optional(string, "filesystem") # Optional
|
||||
config = optional(map(string), {}) # Optional
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
resource "incus_profile" "this" {
|
||||
name = var.name
|
||||
description = var.description
|
||||
project = var.project
|
||||
config = var.config
|
||||
|
||||
dynamic "device" {
|
||||
for_each = var.devices
|
||||
content {
|
||||
name = device.value.name
|
||||
type = device.value.type
|
||||
properties = device.value.properties
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
output "name" {
|
||||
description = "Name of the created Incus profile"
|
||||
value = incus_profile.this.name
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
variable "name" {
|
||||
description = "Name of the Incus profile"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
description = "Optional description of the profile"
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "project" {
|
||||
description = "Project where the profile will be created"
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "config" {
|
||||
description = "Map of Incus profile configuration settings"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "devices" {
|
||||
description = <<EOT
|
||||
List of device blocks. Each device is a map with:
|
||||
- name (string)
|
||||
- type (string)
|
||||
- properties (map(string))
|
||||
EOT
|
||||
type = list(object({
|
||||
name = string
|
||||
type = string
|
||||
properties = map(string)
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "0.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
resource "incus_project" "this" {
|
||||
name = var.name
|
||||
description = var.description
|
||||
|
||||
config = {
|
||||
# Features
|
||||
"features.images" = var.features_images
|
||||
"features.networks" = var.features_networks
|
||||
"features.networks.zones" = var.features_networks_zones
|
||||
"features.profiles" = var.features_profiles
|
||||
"features.storage.buckets" = var.features_storage_buckets
|
||||
"features.storage.volumes" = var.features_storage_volumes
|
||||
|
||||
# Limits
|
||||
"limits.containers" = var.limits_containers
|
||||
"limits.cpu" = var.limits_cpu
|
||||
"limits.disk" = var.limits_disk
|
||||
"limits.instances" = var.limits_instances
|
||||
"limits.memory" = var.limits_memory
|
||||
"limits.networks" = var.limits_networks
|
||||
"limits.processes" = var.limits_processes
|
||||
"limits.virtual-machines" = var.limits_virtual_machines
|
||||
}
|
||||
|
||||
# Dynamic block for per-pool disk limits, if defined
|
||||
dynamic "config" {
|
||||
for_each = var.limits_disk_pool
|
||||
content {
|
||||
key = "limits.disk.pool.${config.key}"
|
||||
value = config.value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
output "name" {
|
||||
description = "The name of the project"
|
||||
value = incus_project.this.name
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
variable "limits_containers" {
|
||||
description = "Maximum number of containers that can be created in the project"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "limits_cpu" {
|
||||
description = "Maximum number of CPUs to use in the project. This value is the maximum of the sum of individual instance CPU limits."
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "limits_disk" {
|
||||
description = "Maximum disk space used by the project. This includes all instance volumes, custom volumes, and images."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "limits_disk_pool" {
|
||||
description = <<EOT
|
||||
Map of storage pool names to disk space limits for each pool.
|
||||
Each key is a POOL_NAME and the value is the maximum aggregate disk space used on that pool.
|
||||
Example:
|
||||
{
|
||||
"default" = "50GB"
|
||||
"ssd" = "100GB"
|
||||
}
|
||||
EOT
|
||||
type = map(string)
|
||||
}
|
||||
|
||||
variable "limits_instances" {
|
||||
description = "Maximum number of instances that can be created in the project"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "limits_memory" {
|
||||
description = "Usage limit for the host’s memory for the project. Sum of individual memory limits on instances."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "limits_networks" {
|
||||
description = "Maximum number of networks that the project can have"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "limits_processes" {
|
||||
description = "Maximum number of processes within the project. This is the sum of the limits.processes on all instances."
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "limits_virtual_machines" {
|
||||
description = "Maximum number of virtual machines that can be created in the project"
|
||||
type = number
|
||||
}
|
||||
|
||||
variable "features_images" {
|
||||
description = "Whether to use a separate set of images for the project (initial value: true)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "features_networks" {
|
||||
description = "Whether to use a separate set of networks for the project (initial value: false)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "features_networks_zones" {
|
||||
description = "Whether to use a separate set of network zones for the project (initial value: false)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "features_profiles" {
|
||||
description = "Whether to use a separate set of profiles for the project (initial value: true)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "features_storage_buckets" {
|
||||
description = "Whether to use a separate set of storage buckets for the project (initial value: true)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "features_storage_volumes" {
|
||||
description = "Whether to use a separate set of storage volumes for the project (initial value: true)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
resource "incus_storage_pool" "this" {
|
||||
name = var.name
|
||||
driver = var.driver
|
||||
description = var.description
|
||||
project = var.project
|
||||
config = var.config
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
output "name" {
|
||||
description = "Name of the storage pool"
|
||||
value = incus_storage_pool.this.name
|
||||
}
|
||||
|
||||
output "driver" {
|
||||
description = "Driver used by the storage pool"
|
||||
value = incus_storage_pool.this.driver
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
variable "name" {
|
||||
description = "Name of the storage pool."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "driver" {
|
||||
description = "Storage Pool driver. Must be one of dir, zfs, lvm, btrfs, ceph, cephfs, or cephobject."
|
||||
type = string
|
||||
validation {
|
||||
condition = contains(["dir", "zfs", "lvm", "btrfs", "ceph", "cephfs", "cephobject"], var.driver)
|
||||
error_message = "Invalid driver. Must be one of: dir, zfs, lvm, btrfs, ceph, cephfs, or cephobject."
|
||||
}
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
description = "Description of the storage pool."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "config" {
|
||||
description = "Map of key/value pairs for storage pool config."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "project" {
|
||||
description = "Name of the project where the storage pool will be stored."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "0.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
resource "incus_storage_volume" "this" {
|
||||
name = var.name
|
||||
pool = var.pool
|
||||
type = var.type
|
||||
config = var.config
|
||||
description = var.description
|
||||
content_type = var.content_type
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
output "name" {
|
||||
description = "Name of the storage volume"
|
||||
value = incus_storage_volume.this.name
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
variable "name" {
|
||||
description = "Name of the storage volume."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "pool" {
|
||||
description = "Name of storage pool to host the volume."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "description" {
|
||||
description = "Description of the volume."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "type" {
|
||||
description = "The 'type' of volume. Default is 'custom'."
|
||||
type = string
|
||||
default = "custom"
|
||||
}
|
||||
|
||||
variable "content_type" {
|
||||
description = "Volume content type. Either 'filesystem' or 'block'."
|
||||
type = string
|
||||
default = "filesystem"
|
||||
}
|
||||
|
||||
variable "config" {
|
||||
description = "Map of key/value pairs of volume config settings. Varies by storage pool."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "0.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user