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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Local .terraform directories
**/.terraform/*
.terraform*

# .tfstate files
*.tfstate
*.tfstate.*

!.terraform.lock.hcl
envrc
out
!deploy/.env
Expand All @@ -9,3 +18,4 @@ deploy/compose/state/webroot/workflow/*
deploy/compose/state/webroot/*.gz
workflow_id.txt
compose.tar.gz
compose.zip
99 changes: 99 additions & 0 deletions deploy/terraform/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions deploy/terraform/cloud-config.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
packages:
- unzip

write_files:
- encoding: b64
content: ${COMPOSE_ZIP}
path: /root/compose.zip

runcmd:
- cd /root/sandbox/compose && unzip /root/compose.zip
- cd /root/sandbox/compose && TINKERBELL_CLIENT_MAC=${WORKER_MAC} TINKERBELL_TEMPLATE_MANIFEST=/manifests/template/ubuntu-equinix-metal.yaml TINKERBELL_HARDWARE_MANIFEST=/manifests/hardware/hardware-equinix-metal.json docker-compose up -d

96 changes: 48 additions & 48 deletions deploy/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Configure the Packet Provider.
# Configure the Equinix Metal Provider.
terraform {
required_providers {
metal = {
source = "equinix/metal"
version = "3.1.0"
version = "3.2.0"
}
null = {
source = "hashicorp/null"
Expand All @@ -23,86 +23,86 @@ provider "metal" {
# Create a new VLAN in datacenter "ewr1"
resource "metal_vlan" "provisioning_vlan" {
description = "provisioning_vlan"
facility = var.facility
metro = var.metro
project_id = var.project_id
}

# Create a device and add it to tf_project_1
resource "metal_device" "tink_worker" {
hostname = "tink-worker"
plan = var.device_type
facilities = [var.facility]
metro = var.metro
operating_system = "custom_ipxe"
ipxe_script_url = "https://boot.netboot.xyz"
always_pxe = "true"
billing_cycle = "hourly"
project_id = var.project_id
}

resource "metal_device_network_type" "tink_worker_network_type" {
device_id = metal_device.tink_worker.id
type = "layer2-individual"
resource "metal_port" "tink_worker_bond0" {
port_id = [for p in metal_device.tink_worker.ports : p.id if p.name == "bond0"][0]
layer2 = true
bonded = false
# vlan_ids = [metal_vlan.provisioning_vlan.id]
# Can't do this: │ Error: vlan assignment batch could not be created: POST https://api.equinix.com/metal/v1/ports/b0bdf6d8-589e-4988-9000-9f49c97a54e1/vlan-assignments/batches: 422 Can't assign VLANs to port b0bdf6d8-589e-4988-9000-9f49c97a54e1, the port is configured for Layer 3 mode., Port b0bdf6d8-589e-4988-9000-9f49c97a54e1 cannot be assigned to VLANs., Bond disabled
}

# Attach VLAN to worker
resource "metal_port_vlan_attachment" "worker" {
depends_on = [metal_device_network_type.tink_worker_network_type]

device_id = metal_device.tink_worker.id
port_name = "eth0"
vlan_vnid = metal_vlan.provisioning_vlan.vxlan
resource "metal_port" "tink_worker_eth0" {
depends_on = [metal_port.tink_worker_bond0]
port_id = [for p in metal_device.tink_worker.ports : p.id if p.name == "eth0"][0]
#layer2 = true
# TODO(displague) the terraform provider is not permitting this, perhaps a bug in the provider validation
# layer2 flag can be set only for bond ports
bonded = false
vlan_ids = [metal_vlan.provisioning_vlan.id]
// vxlan_ids = [1000]
}


# Create a device and add it to tf_project_1
resource "metal_device" "tink_provisioner" {
hostname = "tink-provisioner"
plan = var.device_type
facilities = [var.facility]
metro = var.metro
operating_system = "ubuntu_20_04"
billing_cycle = "hourly"
project_id = var.project_id
user_data = file("setup.sh")
user_data = data.cloudinit_config.setup.rendered
}

resource "metal_device_network_type" "tink_provisioner_network_type" {
device_id = metal_device.tink_provisioner.id
type = "hybrid"
# Provisioners eth1 (unbonded) is attached to the provisioning VLAN
resource "metal_port" "eth1" {
port_id = [for p in metal_device.tink_provisioner.ports : p.id if p.name == "eth1"][0]
bonded = false
vlan_ids = [metal_vlan.provisioning_vlan.id]
}

# Attach VLAN to provisioner
resource "metal_port_vlan_attachment" "provisioner" {
depends_on = [metal_device_network_type.tink_provisioner_network_type]
device_id = metal_device.tink_provisioner.id
port_name = "eth1"
vlan_vnid = metal_vlan.provisioning_vlan.vxlan
data "archive_file" "compose" {
type = "zip"
source_dir = "${path.module}/../compose"
output_path = "${path.module}/compose.zip"
}
Comment on lines +80 to 84
Copy link
Contributor

@mmlb mmlb Mar 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must we go with zip here to make this a module? Having to install unzip makes for a runtime failure (wan network issue for example...) vs using local-exec & tar the failure will happen early and solved "once".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zip is what is available today in the Terraform module. Taking advantage of what is available in Terraform reduces our dependence on local compression tools.

https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/archive_file

hashicorp/terraform-provider-archive#29

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have other network dependencies that would fail with zip, be it package installs or Tink configuration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zip is what is available today in the Terraform module. Taking advantage of what is available in Terraform reduces our dependence on local compression tools.

But with a remote/additional dependence on ubuntu mirrors for every provision. Its a once/now vs always/later tradeoff, once is better than always and now is better than later.Its very unlikely that tar is not around, and we can probably lean on git archive if that were to be an issue anyway, it has built in support for tar (plain tar, git requires gzip for gz compression).

registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/archive_file

hashicorp/terraform-provider-archive#29

hashicorp/terraform-provider-archive#29 (comment) is pretty damning though(its likely not going to get tar.gz support and may go away all together). We'll always have to require installing unzip, even after this ubuntu goes EOL and the mirror url changes and we can't actually install (long time from now yes, but still...).

We have other network dependencies that would fail with zip, be it package installs or Tink configuration.

We don't install any other packages except for zip right? I mean specifically in userdata/cloud-config. I find it much easier to see status/track progress and debug issues using the remote-exec provisioner instead of userdata/cloud-init. I get rid of userdata completely in #126 because of this.

zip is the only hang up I have for this PR, it feels like a "it ain't broke so don't fix" (afaik at least). That being said I don't want to delay the rest of the PR further over issues that aren't super likely to happen or would be minor annoyances. So I'll 👍 it, you can keep the zip in or remove up to you :D


locals {
compose_zip = data.archive_file.compose.output_size > 0 ? filebase64("${path.module}/compose.zip") : ""
}

data "cloudinit_config" "setup" {
depends_on = [
data.archive_file.compose,
]
gzip = false # not supported on Equinix Metal
base64_encode = false # not supported on Equinix Metal

resource "null_resource" "setup" {
connection {
type = "ssh"
user = "root"
host = metal_device.tink_provisioner.network[0].address
agent = var.use_ssh_agent
private_key = var.use_ssh_agent ? null : file(var.ssh_private_key)
}

# need to tar the compose directory because the 'provisioner "file"' does not preserve file permissions
provisioner "local-exec" {
command = "cd ../ && tar zcvf compose.tar.gz compose"
}

provisioner "file" {
source = "../compose.tar.gz"
destination = "/root/compose.tar.gz"
part {
content_type = "text/x-shellscript"
content = file("${path.module}/setup.sh")
}

provisioner "remote-exec" {
inline = [
"cd /root && tar zxvf /root/compose.tar.gz -C /root/sandbox",
"cd /root/sandbox/compose && TINKERBELL_CLIENT_MAC=${metal_device.tink_worker.ports[1].mac} TINKERBELL_TEMPLATE_MANIFEST=/manifests/template/ubuntu-equinix-metal.yaml TINKERBELL_HARDWARE_MANIFEST=/manifests/hardware/hardware-equinix-metal.json docker-compose up -d",
]
part {
content_type = "text/cloud-config"
content = templatefile("${path.module}/cloud-config.cfg", {
COMPOSE_ZIP = local.compose_zip
WORKER_MAC = metal_device.tink_worker.ports[1].mac
})
}
}
8 changes: 4 additions & 4 deletions deploy/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ variable "project_id" {
type = string
}

variable "facility" {
description = "Packet facility to provision in"
variable "metro" {
description = "Equinix Metal metro to provision in"
type = string
default = "sjc1"
default = "sv"
}

variable "device_type" {
Expand All @@ -30,4 +30,4 @@ variable "ssh_private_key" {
type = string
description = "ssh private key file to use"
default = "~/.ssh/id_rsa"
}
}
4 changes: 2 additions & 2 deletions docs/quickstarts/TERRAFORMEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ This option will also show you how to create a machine to provision.
Or if you have the [Equinix Metal CLI](https://github.com/equinix/metal-cli) installed run the following:

```bash
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[1].values.id')
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[3].values.id')
```

5. Watch the provision complete
Expand Down Expand Up @@ -94,7 +94,7 @@ This option will also show you how to create a machine to provision.
Now reboot the `tink-worker` via the [Equinix Metal Web UI](https://console.equinix.com), or if you have the [Equinix Metal CLI](https://github.com/equinix/metal-cli) installed run the following:

```bash
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[1].values.id')
metal device reboot -i $(terraform show -json | jq -r '.values.root_module.resources[3].values.id')
```

7. Login to the machine
Expand Down