Skip to content

Commit 1f85f8f

Browse files
anshulsaoclaude
andcommitted
feat(vultr): add managed DB (redis/mysql/kafka), compute & load_balancer modules
Datastores (vultr_database engines), cloned from postgres/vultr: - datastore/redis/vultr (Valkey; versions 8.1/9.0; eviction_policy + backup window) - datastore/mysql/vultr (versions 8/8.4; slow_query_log/long_query_time/require_primary_key) - datastore/kafka/vultr (versions 3.8-4.1; kafka_rest/schema_registry/kafka_connect) Compute + LB (VM tier, count-scaled): - compute/vultr (vultr_instance, configurable count, ssh keys, startup script, managed firewall, VPC attach) -> @facets/vultr-instance-details - load_balancer/vultr (vultr_load_balancer fronting compute instances; forwarding rules, health check, ssl_redirect) -> @facets/vultr-load-balancer Also: postgres/vultr retrofitted with optional VPC attach (network input -> vpc_id). New output types: @facets/vultr-instance-details, @facets/vultr-load-balancer. Deploy-tested green on demo CP (VPC-attached): postgres, mysql, redis, compute, load_balancer. kafka config-validated (passed plan+version; blocked only by account monthly fee limit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 4b84872 commit 1f85f8f

30 files changed

Lines changed: 1509 additions & 0 deletions

File tree

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
intent: compute
2+
flavor: vultr
3+
version: "1.0"
4+
clouds:
5+
- kubernetes
6+
description: Vultr cloud compute instances (count-scaled VMs) with SSH keys, startup script, and optional firewall
7+
intentDetails:
8+
type: Cloud & Infrastructure
9+
description: Vultr cloud compute virtual machines
10+
displayName: Compute
11+
iconUrl: https://raw.githubusercontent.com/Facets-cloud/facets-modules-redesign/main/icons/compute_engine.svg
12+
spec:
13+
title: Vultr Compute Instances
14+
description: One or more identical Vultr cloud compute instances
15+
type: object
16+
x-ui-order:
17+
- region
18+
- sizing
19+
- image
20+
- networking
21+
- access
22+
- firewall
23+
properties:
24+
region:
25+
type: string
26+
title: Region
27+
description: Vultr region; defaults to the cloud account region when empty
28+
x-ui-overrides-only: true
29+
sizing:
30+
type: object
31+
title: Sizing
32+
x-ui-order:
33+
- plan
34+
- count
35+
properties:
36+
plan:
37+
type: string
38+
title: Plan
39+
description: "Vultr compute plan slug (e.g. vc2-1c-1gb, vc2-1c-2gb, vhf-1c-1gb). List via the Vultr API (GET /v2/plans)."
40+
default: vc2-1c-1gb
41+
x-ui-placeholder: vc2-1c-1gb
42+
count:
43+
type: integer
44+
title: Instance Count
45+
description: Number of identical instances to provision (horizontal scaling)
46+
minimum: 1
47+
maximum: 20
48+
default: 2
49+
required:
50+
- plan
51+
- count
52+
image:
53+
type: object
54+
title: Image
55+
properties:
56+
os_id:
57+
type: integer
58+
title: OS ID
59+
description: "Vultr OS ID (e.g. 1743 = Ubuntu 22.04 x64, 2136 = Ubuntu 24.04 x64). List via GET /v2/os."
60+
default: 1743
61+
required:
62+
- os_id
63+
networking:
64+
type: object
65+
title: Networking
66+
properties:
67+
attach_vpc:
68+
type: boolean
69+
title: Attach to VPC
70+
description: Attach instances to the wired VPC (requires the network input)
71+
default: true
72+
enable_ipv6:
73+
type: boolean
74+
title: Enable IPv6
75+
default: false
76+
access:
77+
type: object
78+
title: Access
79+
properties:
80+
ssh_public_keys:
81+
type: array
82+
title: SSH Public Keys
83+
description: Public keys installed on the instances
84+
default: []
85+
items:
86+
type: string
87+
startup_script:
88+
type: string
89+
title: Startup Script
90+
description: Shell script run on first boot
91+
x-ui-widget: textarea
92+
default: ""
93+
firewall:
94+
type: object
95+
title: Firewall
96+
x-ui-toggle: true
97+
properties:
98+
manage:
99+
type: boolean
100+
title: Manage Firewall
101+
description: Create a managed firewall group for these instances
102+
default: false
103+
open_ports:
104+
type: object
105+
title: Open Ports
106+
description: Inbound rules; key is a unique rule id
107+
default: {}
108+
patternProperties:
109+
".*":
110+
type: object
111+
properties:
112+
port:
113+
type: string
114+
title: Port
115+
protocol:
116+
type: string
117+
title: Protocol
118+
enum:
119+
- tcp
120+
- udp
121+
default: tcp
122+
source:
123+
type: string
124+
title: Source CIDR
125+
default: 0.0.0.0/0
126+
required:
127+
- port
128+
required:
129+
- sizing
130+
- image
131+
inputs:
132+
vultr_cloud_account:
133+
type: "@facets/vultr_cloud_account"
134+
optional: false
135+
displayName: Vultr Cloud Account
136+
description: Vultr provider configuration and default region
137+
providers:
138+
- vultr
139+
network:
140+
type: "@facets/vultr-vpc-details"
141+
optional: true
142+
displayName: VPC Network
143+
description: Optional VPC to attach instances to
144+
providers: []
145+
outputs:
146+
default:
147+
type: "@facets/vultr-instance-details"
148+
title: Vultr Compute Instances
149+
sample:
150+
kind: compute
151+
flavor: vultr
152+
version: "1.0"
153+
disabled: true
154+
spec:
155+
sizing:
156+
plan: vc2-1c-1gb
157+
count: 2
158+
image:
159+
os_id: 1743
160+
networking:
161+
attach_vpc: true
162+
enable_ipv6: false
163+
access:
164+
ssh_public_keys: []
165+
startup_script: ""
166+
firewall:
167+
manage: false
168+
open_ports: {}
169+
iac:
170+
validated_files:
171+
- main.tf
172+
- variables.tf
173+
- outputs.tf
174+
- versions.tf

modules/compute/vultr/1.0/main.tf

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Vultr Compute Instances Module
2+
# Provisions one or more identical Vultr cloud compute instances (count-scaled),
3+
# with optional SSH keys, startup script, VPC attach, and managed firewall.
4+
5+
module "name" {
6+
source = "github.com/Facets-cloud/facets-utility-modules//name"
7+
environment = var.environment
8+
limit = 32
9+
resource_name = var.instance_name
10+
resource_type = "compute"
11+
}
12+
13+
locals {
14+
region = coalesce(try(var.instance.spec.region, null), var.inputs.vultr_cloud_account.attributes.region)
15+
vpc_ids = (var.instance.spec.networking.attach_vpc && var.inputs.network != null) ? [var.inputs.network.attributes.vpc_id] : null
16+
has_script = length(trimspace(var.instance.spec.access.startup_script)) > 0
17+
}
18+
19+
resource "vultr_ssh_key" "this" {
20+
for_each = { for idx, k in var.instance.spec.access.ssh_public_keys : tostring(idx) => k }
21+
name = "${module.name.name}-${each.key}"
22+
ssh_key = each.value
23+
}
24+
25+
resource "vultr_startup_script" "this" {
26+
count = local.has_script ? 1 : 0
27+
name = module.name.name
28+
script = base64encode(var.instance.spec.access.startup_script)
29+
}
30+
31+
resource "vultr_firewall_group" "this" {
32+
count = var.instance.spec.firewall.manage ? 1 : 0
33+
description = module.name.name
34+
}
35+
36+
resource "vultr_firewall_rule" "this" {
37+
for_each = var.instance.spec.firewall.manage ? var.instance.spec.firewall.open_ports : {}
38+
firewall_group_id = vultr_firewall_group.this[0].id
39+
protocol = each.value.protocol
40+
ip_type = "v4"
41+
subnet = split("/", each.value.source)[0]
42+
subnet_size = tonumber(split("/", each.value.source)[1])
43+
port = each.value.port
44+
}
45+
46+
resource "vultr_instance" "this" {
47+
count = var.instance.spec.sizing.count
48+
region = local.region
49+
plan = var.instance.spec.sizing.plan
50+
os_id = var.instance.spec.image.os_id
51+
label = "${module.name.name}-${count.index}"
52+
hostname = "${module.name.name}-${count.index}"
53+
enable_ipv6 = var.instance.spec.networking.enable_ipv6
54+
vpc_ids = local.vpc_ids
55+
ssh_key_ids = [for k in vultr_ssh_key.this : k.id]
56+
script_id = local.has_script ? vultr_startup_script.this[0].id : null
57+
firewall_group_id = var.instance.spec.firewall.manage ? vultr_firewall_group.this[0].id : null
58+
activation_email = false
59+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
locals {
2+
output_attributes = {
3+
instance_ids = [for i in vultr_instance.this : i.id]
4+
instance_id = length(vultr_instance.this) > 0 ? vultr_instance.this[0].id : ""
5+
main_ips = [for i in vultr_instance.this : i.main_ip]
6+
main_ip = length(vultr_instance.this) > 0 ? vultr_instance.this[0].main_ip : ""
7+
internal_ips = [for i in vultr_instance.this : i.internal_ip]
8+
region = local.region
9+
plan = var.instance.spec.sizing.plan
10+
firewall_group_id = var.instance.spec.firewall.manage ? vultr_firewall_group.this[0].id : ""
11+
}
12+
13+
output_interfaces = {
14+
ssh = {
15+
host = length(vultr_instance.this) > 0 ? vultr_instance.this[0].main_ip : ""
16+
port = "22"
17+
username = "root"
18+
password = length(vultr_instance.this) > 0 ? vultr_instance.this[0].default_password : ""
19+
secrets = ["password"]
20+
}
21+
}
22+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
variable "instance" {
2+
description = "Vultr cloud compute instances (count-scaled)"
3+
type = object({
4+
kind = string
5+
flavor = string
6+
version = string
7+
spec = object({
8+
region = optional(string)
9+
sizing = object({
10+
plan = string
11+
count = number
12+
})
13+
image = object({
14+
os_id = number
15+
})
16+
networking = optional(object({
17+
attach_vpc = optional(bool, true)
18+
enable_ipv6 = optional(bool, false)
19+
}), {})
20+
access = optional(object({
21+
ssh_public_keys = optional(list(string), [])
22+
startup_script = optional(string, "")
23+
}), {})
24+
firewall = optional(object({
25+
manage = optional(bool, false)
26+
open_ports = optional(map(object({
27+
port = string
28+
protocol = optional(string, "tcp")
29+
source = optional(string, "0.0.0.0/0")
30+
})), {})
31+
}), {})
32+
})
33+
})
34+
35+
validation {
36+
condition = var.instance.spec.sizing.count >= 1 && var.instance.spec.sizing.count <= 20
37+
error_message = "count must be between 1 and 20."
38+
}
39+
}
40+
41+
variable "instance_name" {
42+
description = "The architectural name for the resource as added in the Facets blueprint designer."
43+
type = string
44+
}
45+
46+
variable "environment" {
47+
description = "An object containing details about the environment."
48+
type = object({
49+
name = string
50+
unique_name = string
51+
cloud_tags = optional(map(string), {})
52+
})
53+
}
54+
55+
variable "inputs" {
56+
description = "A map of inputs requested by the module developer."
57+
type = object({
58+
vultr_cloud_account = object({
59+
attributes = object({
60+
api_key = string
61+
region = string
62+
})
63+
})
64+
network = optional(object({
65+
attributes = object({
66+
vpc_id = string
67+
})
68+
}))
69+
})
70+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
vultr = {
6+
source = "vultr/vultr"
7+
version = ">= 2.0.0"
8+
}
9+
}
10+
}

0 commit comments

Comments
 (0)