Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions modules/compute/vultr/1.0/facets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
intent: compute
flavor: vultr
version: "1.0"
clouds:
- kubernetes
description: Vultr cloud compute instances (count-scaled VMs) with SSH keys, startup script, and optional firewall
intentDetails:
type: Cloud & Infrastructure
description: Vultr cloud compute virtual machines
displayName: Compute
iconUrl: https://raw.githubusercontent.com/Facets-cloud/facets-modules-redesign/main/icons/compute_engine.svg
spec:
title: Vultr Compute Instances
description: One or more identical Vultr cloud compute instances
type: object
x-ui-order:
- region
- sizing
- image
- networking
- access
- firewall
properties:
region:
type: string
title: Region
description: Vultr region; defaults to the cloud account region when empty
x-ui-overrides-only: true
sizing:
type: object
title: Sizing
x-ui-order:
- plan
- count
properties:
plan:
type: string
title: Plan
description: "Vultr compute plan slug (e.g. vc2-1c-1gb, vc2-1c-2gb, vhf-1c-1gb). List via the Vultr API (GET /v2/plans)."
default: vc2-1c-1gb
x-ui-placeholder: vc2-1c-1gb
count:
type: integer
title: Instance Count
description: Number of identical instances to provision (horizontal scaling)
minimum: 1
maximum: 20
default: 2
required:
- plan
- count
image:
type: object
title: Image
properties:
os_id:
type: integer
title: OS ID
description: "Vultr OS ID (e.g. 1743 = Ubuntu 22.04 x64, 2136 = Ubuntu 24.04 x64). List via GET /v2/os."
default: 1743
required:
- os_id
networking:
type: object
title: Networking
properties:
attach_vpc:
type: boolean
title: Attach to VPC
description: Attach instances to the wired VPC (requires the network input)
default: true
enable_ipv6:
type: boolean
title: Enable IPv6
default: false
access:
type: object
title: Access
properties:
ssh_public_keys:
type: array
title: SSH Public Keys
description: Public keys installed on the instances
default: []
items:
type: string
startup_script:
type: string
title: Startup Script
description: Shell script run on first boot
x-ui-widget: textarea
default: ""
firewall:
type: object
title: Firewall
x-ui-toggle: true
properties:
manage:
type: boolean
title: Manage Firewall
description: Create a managed firewall group for these instances
default: false
open_ports:
type: object
title: Open Ports
description: Inbound rules; key is a unique rule id
default: {}
patternProperties:
".*":
type: object
properties:
port:
type: string
title: Port
protocol:
type: string
title: Protocol
enum:
- tcp
- udp
default: tcp
source:
type: string
title: Source CIDR
default: 0.0.0.0/0
required:
- port
required:
- sizing
- image
inputs:
vultr_cloud_account:
type: "@facets/vultr_cloud_account"
optional: false
displayName: Vultr Cloud Account
description: Vultr provider configuration and default region
providers:
- vultr
network:
type: "@facets/vultr-vpc-details"
optional: true
displayName: VPC Network
description: Optional VPC to attach instances to
providers: []
outputs:
default:
type: "@facets/vultr-instance-details"
title: Vultr Compute Instances
sample:
kind: compute
flavor: vultr
version: "1.0"
disabled: true
spec:
sizing:
plan: vc2-1c-1gb
count: 2
image:
os_id: 1743
networking:
attach_vpc: true
enable_ipv6: false
access:
ssh_public_keys: []
startup_script: ""
firewall:
manage: false
open_ports: {}
iac:
validated_files:
- main.tf
- variables.tf
- outputs.tf
- versions.tf
59 changes: 59 additions & 0 deletions modules/compute/vultr/1.0/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Vultr Compute Instances Module
# Provisions one or more identical Vultr cloud compute instances (count-scaled),
# with optional SSH keys, startup script, VPC attach, and managed firewall.

module "name" {
source = "github.com/Facets-cloud/facets-utility-modules//name"
environment = var.environment
limit = 32
resource_name = var.instance_name
resource_type = "compute"
}

locals {
region = coalesce(try(var.instance.spec.region, null), var.inputs.vultr_cloud_account.attributes.region)
vpc_ids = (var.instance.spec.networking.attach_vpc && var.inputs.network != null) ? [var.inputs.network.attributes.vpc_id] : null
has_script = length(trimspace(var.instance.spec.access.startup_script)) > 0
}

resource "vultr_ssh_key" "this" {
for_each = { for idx, k in var.instance.spec.access.ssh_public_keys : tostring(idx) => k }
name = "${module.name.name}-${each.key}"
ssh_key = each.value
}

resource "vultr_startup_script" "this" {
count = local.has_script ? 1 : 0
name = module.name.name
script = base64encode(var.instance.spec.access.startup_script)
}

resource "vultr_firewall_group" "this" {
count = var.instance.spec.firewall.manage ? 1 : 0
description = module.name.name
}

resource "vultr_firewall_rule" "this" {
for_each = var.instance.spec.firewall.manage ? var.instance.spec.firewall.open_ports : {}
firewall_group_id = vultr_firewall_group.this[0].id
protocol = each.value.protocol
ip_type = "v4"
subnet = split("/", each.value.source)[0]
subnet_size = tonumber(split("/", each.value.source)[1])
port = each.value.port
}

resource "vultr_instance" "this" {
count = var.instance.spec.sizing.count
region = local.region
plan = var.instance.spec.sizing.plan
os_id = var.instance.spec.image.os_id
label = "${module.name.name}-${count.index}"
hostname = "${module.name.name}-${count.index}"
enable_ipv6 = var.instance.spec.networking.enable_ipv6
vpc_ids = local.vpc_ids
ssh_key_ids = [for k in vultr_ssh_key.this : k.id]
script_id = local.has_script ? vultr_startup_script.this[0].id : null
firewall_group_id = var.instance.spec.firewall.manage ? vultr_firewall_group.this[0].id : null
activation_email = false
}
22 changes: 22 additions & 0 deletions modules/compute/vultr/1.0/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
locals {
output_attributes = {
instance_ids = [for i in vultr_instance.this : i.id]
instance_id = length(vultr_instance.this) > 0 ? vultr_instance.this[0].id : ""
main_ips = [for i in vultr_instance.this : i.main_ip]
main_ip = length(vultr_instance.this) > 0 ? vultr_instance.this[0].main_ip : ""
internal_ips = [for i in vultr_instance.this : i.internal_ip]
region = local.region
plan = var.instance.spec.sizing.plan
firewall_group_id = var.instance.spec.firewall.manage ? vultr_firewall_group.this[0].id : ""
}

output_interfaces = {
ssh = {
host = length(vultr_instance.this) > 0 ? vultr_instance.this[0].main_ip : ""
port = "22"
username = "root"
password = length(vultr_instance.this) > 0 ? vultr_instance.this[0].default_password : ""
secrets = ["password"]
}
}
}
70 changes: 70 additions & 0 deletions modules/compute/vultr/1.0/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
variable "instance" {
description = "Vultr cloud compute instances (count-scaled)"
type = object({
kind = string
flavor = string
version = string
spec = object({
region = optional(string)
sizing = object({
plan = string
count = number
})
image = object({
os_id = number
})
networking = optional(object({
attach_vpc = optional(bool, true)
enable_ipv6 = optional(bool, false)
}), {})
access = optional(object({
ssh_public_keys = optional(list(string), [])
startup_script = optional(string, "")
}), {})
firewall = optional(object({
manage = optional(bool, false)
open_ports = optional(map(object({
port = string
protocol = optional(string, "tcp")
source = optional(string, "0.0.0.0/0")
})), {})
}), {})
})
})

validation {
condition = var.instance.spec.sizing.count >= 1 && var.instance.spec.sizing.count <= 20
error_message = "count must be between 1 and 20."
}
}

variable "instance_name" {
description = "The architectural name for the resource as added in the Facets blueprint designer."
type = string
}

variable "environment" {
description = "An object containing details about the environment."
type = object({
name = string
unique_name = string
cloud_tags = optional(map(string), {})
})
}

variable "inputs" {
description = "A map of inputs requested by the module developer."
type = object({
vultr_cloud_account = object({
attributes = object({
api_key = string
region = string
})
})
network = optional(object({
attributes = object({
vpc_id = string
})
}))
})
}
10 changes: 10 additions & 0 deletions modules/compute/vultr/1.0/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"

required_providers {
vultr = {
source = "vultr/vultr"
version = ">= 2.0.0"
}
}
}
Loading