diff --git a/prepare-vms/infra/hetzner b/prepare-vms/infra/hetzner index bfe50ced..db3220be 100644 --- a/prepare-vms/infra/hetzner +++ b/prepare-vms/infra/hetzner @@ -1,5 +1,2 @@ -INFRACLASS=hetzner -if ! [ -f ~/.config/hcloud/cli.toml ]; then - warning "~/.config/hcloud/cli.toml not found." - warning "Make sure that the Hetzner CLI (hcloud) is installed and configured." -fi +INFRACLASS=terraform +TERRAFORM=hetzner diff --git a/prepare-vms/lib/infra/hetzner.sh b/prepare-vms/lib/infra/hetzner.sh deleted file mode 100644 index ed109b46..00000000 --- a/prepare-vms/lib/infra/hetzner.sh +++ /dev/null @@ -1,57 +0,0 @@ -if ! command -v hcloud >/dev/null; then - warning "Hetzner CLI (hcloud) not found." -fi -if ! [ -f ~/.config/hcloud/cli.toml ]; then - warning "~/.config/hcloud/cli.toml not found." -fi - -infra_list() { - [ "$(hcloud server list -o json)" = "null" ] && return - - hcloud server list -o json | - jq -r '.[] | [.id, .name , .status, .server_type.name] | @tsv' -} - -infra_start() { - COUNT=$1 - - HETZNER_INSTANCE_TYPE=${HETZNER_INSTANCE_TYPE-cx21} - HETZNER_DATACENTER=${HETZNER_DATACENTER-nbg1-dc3} - HETZNER_IMAGE=${HETZNER_IMAGE-168855} - - for I in $(seq 1 $COUNT); do - NAME=$(printf "%s-%03d" $TAG $I) - sep "Starting instance $I/$COUNT" - info " Datacenter: $HETZNER_DATACENTER" - info " Name: $NAME" - info " Instance type: $HETZNER_INSTANCE_TYPE" - hcloud server create \ - --type=${HETZNER_INSTANCE_TYPE} \ - --datacenter=${HETZNER_DATACENTER} \ - --image=${HETZNER_IMAGE} \ - --name=$NAME \ - --label=tag=$TAG \ - --ssh-key ~/.ssh/id_rsa.pub - done - - hetzner_get_ips_by_tag $TAG > tags/$TAG/ips.txt -} - -infra_stop() { - for ID in $(hetzner_get_ids_by_tag $TAG); do - info "Scheduling deletion of instance $ID..." - hcloud server delete $ID & - done - info "Waiting for deletion to complete..." - wait -} - -hetzner_get_ids_by_tag() { - TAG=$1 - hcloud server list --selector=tag=$TAG -o json | jq -r .[].name -} - -hetzner_get_ips_by_tag() { - TAG=$1 - hcloud server list --selector=tag=$TAG -o json | jq -r .[].public_net.ipv4.ip -} diff --git a/prepare-vms/terraform/hetzner/main.tf b/prepare-vms/terraform/hetzner/main.tf new file mode 100644 index 00000000..de530aa7 --- /dev/null +++ b/prepare-vms/terraform/hetzner/main.tf @@ -0,0 +1,34 @@ +resource "hcloud_server" "_" { + count = var.how_many_nodes + name = format("%s-%04d", var.prefix, count.index + 1) + location = var.location + server_type = var.size + ssh_keys = [hcloud_ssh_key._.id] + image = "ubuntu-22.04" +} + +resource "hcloud_ssh_key" "_" { + name = var.prefix + public_key = tls_private_key.ssh.public_key_openssh +} + +output "ip_addresses" { + value = join("", formatlist("%s\n", hcloud_server._.*.ipv4_address)) +} + +resource "tls_private_key" "ssh" { + algorithm = "RSA" + rsa_bits = "4096" +} + +resource "local_file" "ssh_private_key" { + content = tls_private_key.ssh.private_key_pem + filename = "id_rsa" + file_permission = "0600" +} + +resource "local_file" "ssh_public_key" { + content = tls_private_key.ssh.public_key_openssh + filename = "id_rsa.pub" + file_permission = "0600" +} diff --git a/prepare-vms/terraform/hetzner/provider.tf b/prepare-vms/terraform/hetzner/provider.tf new file mode 100644 index 00000000..4776603d --- /dev/null +++ b/prepare-vms/terraform/hetzner/provider.tf @@ -0,0 +1,18 @@ +terraform { + required_version = ">= 1" + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + } + } +} + +/* +Okay, the following is pretty gross - it uses the first token found in the hcloud CLI +configuration file. We don't use Hetzner much anyway, and when we do, we only have one +profile ever, and we want this thing to Just Work; so this should do for now, but might +need to be improved if others actively use Hetzner to provision training labs. +*/ +provider hcloud { + token = regex("token = \"([A-Za-z0-9]+)\"", file("~/.config/hcloud/cli.toml"))[0] +} \ No newline at end of file diff --git a/prepare-vms/terraform/hetzner/variables.tf b/prepare-vms/terraform/hetzner/variables.tf new file mode 100644 index 00000000..85269335 --- /dev/null +++ b/prepare-vms/terraform/hetzner/variables.tf @@ -0,0 +1,42 @@ +variable "prefix" { + type = string + default = "provisioned-with-terraform" +} + +variable "how_many_nodes" { + type = number + default = 2 +} + +/* +$ hcloud server-type list | grep shared +1 cx11 1 shared 2.0 GB 20 GB local +3 cx21 2 shared 4.0 GB 40 GB local +5 cx31 2 shared 8.0 GB 80 GB local +7 cx41 4 shared 16.0 GB 160 GB local +9 cx51 8 shared 32.0 GB 240 GB local +22 cpx11 2 shared 2.0 GB 40 GB local +23 cpx21 3 shared 4.0 GB 80 GB local +24 cpx31 4 shared 8.0 GB 160 GB local +25 cpx41 8 shared 16.0 GB 240 GB local +26 cpx51 16 shared 32.0 GB 360 GB local +*/ + +variable "size" { + type = string + default = "cx21" +} + +/* +$ hcloud location list +ID NAME DESCRIPTION NETWORK ZONE COUNTRY CITY +1 fsn1 Falkenstein DC Park 1 eu-central DE Falkenstein +2 nbg1 Nuremberg DC Park 1 eu-central DE Nuremberg +3 hel1 Helsinki DC Park 1 eu-central FI Helsinki +4 ash Ashburn, VA us-east US Ashburn, VA +5 hil Hillsboro, OR us-west US Hillsboro, OR +*/ +variable "location" { + type = string + default = "hel1" +}