-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: deploy to existing projects in selected metro #93
Conversation
9b91104
to
463a768
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution. The PR failed formatting checks which we use to keep the code consistently indented. Can you have a look - https://github.com/rancherlabs/terraform-harvester-equinix/actions/runs/10745278454/job/29809400512?pr=93
@dnoland1 -- updated with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
terraform plan is failing - https://github.com/rancherlabs/terraform-harvester-equinix/actions/runs/10748090068/job/29813323509?pr=93
The equinix_metal_project datasource will only take name or project_id, mutually exclusive, so the missing argument has to be sent as I updated the logic and added precondition checks (required bumping to min TF 1.2). I verified that the datasource worked when I looked up by project name or id. I also noticed that datasource was not needed when metal_create_project was set, so we |
CI is currently failing in because TF_VAR_project_name is not defined in the contributor PR pipeline. I believe this would succeed in the e2e pipeline. The requirement for either a project_id or project_name is real and it makes sense that the validation fails in the current state. We could add a TF_VAR_project_name to this workflow or change the defaults: set a default name "harvester_something" and create_project=true, these will make organization_id a stronger requirement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @displague,
I tried to contribute to your Fork, but I received a "permission denied".
Anyway, I'll share the changes I made below:
data.tf
data "equinix_metal_project" "project" {
count = var.metal_create_project ? 0 : 1
name = var.project_name == "" ? null : var.project_name
project_id = var.project_id == "" ? null : var.project_id
lifecycle {
precondition {
condition = !(var.project_name != "" && var.project_id != "")
error_message = "Only one of project_name or project_id can be set"
}
precondition {
condition = var.project_name != "" || var.project_id != ""
error_message = "One of project_name or project_id must be set when metal_create_project is false"
}
}
}
data "equinix_metal_ip_block_ranges" "address_block" {
project_id = local.project_id
metro = (var.spot_instance && var.use_cheapest_metro && local.cheapest_metro_price != null) ? local.cheapest_metro_price.metro : var.metro
}
data "equinix_metal_spot_market_request" "seed_req" {
count = var.spot_instance ? 1 : 0
request_id = equinix_metal_spot_market_request.seed_spot_request.0.id
}
data "equinix_metal_spot_market_request" "join_req" {
count = var.spot_instance ? var.node_count - 1 : 0
request_id = equinix_metal_spot_market_request.join_spot_request[count.index].id
}
data "equinix_metal_device" "seed_device" {
device_id = var.spot_instance ? data.equinix_metal_spot_market_request.seed_req.0.device_ids[0] : equinix_metal_device.seed.0.id
}
data "equinix_metal_device" "join_devices" {
count = var.node_count - 1
device_id = var.spot_instance ? data.equinix_metal_spot_market_request.join_req[count.index].device_ids[0] : equinix_metal_device.join[count.index].id
}
data "http" "prices" {
count = var.spot_instance && var.use_cheapest_metro ? 1 : 0
url = "https://api.equinix.com/metal/v1/market/spot/prices/metros"
method = "GET"
request_headers = {
"X-Auth-Token" = var.api_key
}
}
Here I fixed the "local.cheapest_metro_price is null" issue during CI plan
variables.tf
variable "harvester_version" {
description = "Harvester version to be installed (Must be a valid version tag from https://github.com/rancherlabs/terraform-harvester-equinix/tree/main/ipxe)"
type = string
default = "v1.3.1"
}
variable "node_count" {
description = "Number of nodes to deploy Harvester cluster"
type = number
default = 3
}
variable "metal_create_project" {
description = "Create a Metal Project if this is 'true'. Else use provided 'project_name'"
type = bool
default = false
}
variable "project_name" {
description = "Name of the Equinix Metal project to deploy into, when not looking up by project_id"
type = string
default = "Harvester Labs"
}
variable "organization_id" {
description = "Equinix Metal organization ID to create or find a project in"
type = string
default = ""
}
variable "project_id" {
description = "Equinix Metal project ID to deploy into, if not creating a new project or looking up by name"
type = string
default = ""
}
variable "plan" {
description = "Size of the servers to be deployed on Equinix metal (https://deploy.equinix.com/developers/docs/metal/hardware/standard-servers/)"
type = string
default = "m3.small.x86"
}
variable "billing_cycle" {
description = "Equinix metal billing/invoice generation schedule (hourly/daily/monthly/yearly)"
type = string
default = "hourly"
}
variable "metro" {
description = "Equinix metal data center location (https://deploy.equinix.com/developers/docs/metal/locations/metros/). Examples: SG,SV,AM,MA,Ny,LA,etc."
type = string
default = "SG"
}
variable "ipxe_script" {
description = "URL to the iPXE script to use for booting the server (harvester_version will be appended to this without the 'v' prefix)"
type = string
default = "https://raw.githubusercontent.com/rancherlabs/terraform-harvester-equinix/main/ipxe/ipxe-"
}
variable "hostname_prefix" {
description = "Prefix for resources to be created in equinix metal"
type = string
default = "harvester-pxe"
}
variable "spot_instance" {
description = "Set to true to use spot instance instead of on demand. Also set your max bid price if true."
type = bool
default = true
}
variable "max_bid_price" {
description = "Maximum bid price for spot request"
type = string
default = "0.75"
}
variable "use_cheapest_metro" {
description = "A boolean variable to control cheapest metro selection"
type = bool
default = true
}
variable "ssh_key" {
description = "Your ssh key, examples: 'github: myghid' or 'ssh-rsa AAAAblahblah== keyname'"
type = string
default = ""
}
variable "num_of_vlans" {
description = "Number of VLANs to be created"
type = number
default = 2
}
variable "rancher_api_url" {
description = "Rancher API endpoint to manager your Harvester cluster"
type = string
default = ""
}
variable "rancher_access_key" {
description = "Rancher access key"
type = string
default = ""
}
variable "rancher_secret_key" {
description = "Rancher secret key"
type = string
default = ""
}
variable "rancher_insecure" {
description = "Allow insecure connections to the Rancher API"
type = bool
default = false
}
variable "api_key" {
description = "Equinix Metal authentication token. Required when using Spot Instances for HTTP pricing lookups. METAL_AUTH_TOKEN should always be set as an environment variable"
type = string
default = ""
}
Here I wrote the variables all with the same style (description, type, default) and assigned a default value to "project_name".
main.tf
locals {
project_id = var.metal_create_project ? equinix_metal_project.new_project[0].id : data.equinix_metal_project.project[0].project_id
metro = (var.spot_instance && var.use_cheapest_metro && local.cheapest_metro_price != null) ? local.cheapest_metro_price.metro : lower(var.metro)
}
// IP attachment to be added to seed node, and this is subsequently assigned as Harvester vip
// in the config.yaml
resource "random_password" "password" {
length = 16
special = false
}
resource "random_password" "token" {
length = 16
special = false
}
resource "equinix_metal_project" "new_project" {
count = var.metal_create_project ? 1 : 0
name = var.project_name
organization_id = var.organization_id == "" ? null : var.organization_id
}
locals {
machine_size = var.plan
pricing_data = (var.spot_instance && var.use_cheapest_metro) ? try(jsondecode(data.http.prices[0].response_body), null) : null
least_bid_price_metro = can(local.pricing_data) && can(local.pricing_data.spot_market_prices) ? flatten([for metro, machines in local.pricing_data.spot_market_prices : [
for machine, details in machines : {
metro = metro
machine = machine
price = details.price
} if machine == local.machine_size
]]) : []
cheapest_metro_price = length(local.least_bid_price_metro) > 0 ? {
price = min([for price in local.least_bid_price_metro : price.price]...),
metro = [for price in local.least_bid_price_metro : price.metro if price.price == min([for price in local.least_bid_price_metro : price.price]...)][0]
} : null
}
## Keeping it commented for debugging purposes. Will remove once verified.
#output "http_response" {
# value = data.http.prices.response_body
#}
resource "equinix_metal_reserved_ip_block" "harvester_vip" {
project_id = local.project_id
metro = local.metro
type = "public_ipv4"
quantity = 1
}
resource "equinix_metal_device" "seed" {
hostname = "${var.hostname_prefix}-1"
count = var.node_count >= 1 && !var.spot_instance ? 1 : 0
plan = var.plan
metro = local.metro
operating_system = "custom_ipxe"
billing_cycle = var.billing_cycle
project_id = local.project_id
ipxe_script_url = "${var.ipxe_script}${element(split("v", var.harvester_version), 1)}"
always_pxe = "false"
user_data = templatefile("${path.module}/create.tpl", { version = var.harvester_version, password = random_password.password.result, token = random_password.token.result, vip = equinix_metal_reserved_ip_block.harvester_vip.network, hostname_prefix = var.hostname_prefix, ssh_key = var.ssh_key, count = "1", cluster_registration_url = var.rancher_api_url != "" ? rancher2_cluster.rancher_cluster[0].cluster_registration_token[0].manifest_url : "" })
}
resource "equinix_metal_spot_market_request" "seed_spot_request" {
count = var.node_count >= 1 && var.spot_instance ? 1 : 0
project_id = local.project_id
max_bid_price = (var.use_cheapest_metro && local.cheapest_metro_price != null) ? local.cheapest_metro_price.price : var.max_bid_price
metro = local.metro
devices_min = 1
devices_max = 1
wait_for_devices = true
instance_parameters {
hostname = "${var.hostname_prefix}-1"
billing_cycle = "hourly"
operating_system = "custom_ipxe"
ipxe_script_url = "${var.ipxe_script}${element(split("v", var.harvester_version), 1)}"
plan = var.plan
userdata = templatefile("${path.module}/create.tpl", { version = var.harvester_version, password = random_password.password.result, token = random_password.token.result, vip = equinix_metal_reserved_ip_block.harvester_vip.network, hostname_prefix = var.hostname_prefix, ssh_key = var.ssh_key, count = "1", cluster_registration_url = var.rancher_api_url != "" ? rancher2_cluster.rancher_cluster[0].cluster_registration_token[0].manifest_url : "" })
}
}
resource "equinix_metal_ip_attachment" "first_address_assignment" {
device_id = var.spot_instance ? data.equinix_metal_spot_market_request.seed_req.0.device_ids[0] : equinix_metal_device.seed.0.id
cidr_notation = join("/", [cidrhost(equinix_metal_reserved_ip_block.harvester_vip.cidr_notation, 0), "32"])
}
resource "equinix_metal_device" "join" {
hostname = "${var.hostname_prefix}-${count.index + 2}"
count = var.spot_instance ? 0 : var.node_count - 1
plan = var.plan
metro = local.metro
operating_system = "custom_ipxe"
billing_cycle = var.billing_cycle
project_id = local.project_id
ipxe_script_url = "${var.ipxe_script}${element(split("v", var.harvester_version), 1)}"
always_pxe = "false"
user_data = templatefile("${path.module}/join.tpl", { version = var.harvester_version, password = random_password.password.result, token = random_password.token.result, seed = equinix_metal_reserved_ip_block.harvester_vip.network, hostname_prefix = var.hostname_prefix, ssh_key = var.ssh_key, count = "${count.index + 2}" })
}
resource "equinix_metal_spot_market_request" "join_spot_request" {
count = var.spot_instance ? var.node_count - 1 : 0
project_id = local.project_id
max_bid_price = (var.use_cheapest_metro && local.cheapest_metro_price != null) ? local.cheapest_metro_price.price : var.max_bid_price
metro = local.metro
devices_min = 1
devices_max = 1
wait_for_devices = true
instance_parameters {
hostname = "${var.hostname_prefix}-${count.index + 2}"
billing_cycle = "hourly"
operating_system = "custom_ipxe"
ipxe_script_url = "${var.ipxe_script}${element(split("v", var.harvester_version), 1)}"
plan = var.plan
userdata = templatefile("${path.module}/join.tpl", { version = var.harvester_version, password = random_password.password.result, token = random_password.token.result, seed = equinix_metal_reserved_ip_block.harvester_vip.network, hostname_prefix = var.hostname_prefix, ssh_key = var.ssh_key, count = "${count.index + 2}" })
}
}
resource "equinix_metal_vlan" "vlans" {
count = var.num_of_vlans
description = "VLAN for ${var.hostname_prefix}"
project_id = local.project_id
metro = local.metro
}
resource "equinix_metal_port_vlan_attachment" "vlan_attach_seed" {
count = var.num_of_vlans
device_id = data.equinix_metal_device.seed_device.id
vlan_vnid = equinix_metal_vlan.vlans[count.index].vxlan
port_name = "bond0"
}
resource "equinix_metal_port_vlan_attachment" "vlan_attach_join" {
count = var.num_of_vlans * (var.node_count - 1)
device_id = data.equinix_metal_device.join_devices[count.index % (var.node_count - 1)].id
vlan_vnid = equinix_metal_vlan.vlans[floor(count.index / (var.node_count - 1))].vxlan
port_name = "bond0"
}
resource "rancher2_cluster" "rancher_cluster" {
name = var.hostname_prefix
count = var.rancher_api_url != "" ? 1 : 0
description = "${var.hostname_prefix} created by Terraform"
}
resource "local_file" "harvester_kubeconfig" {
count = var.rancher_api_url != "" ? 1 : 0
content = rancher2_cluster.rancher_cluster[0].kube_config
filename = "${var.hostname_prefix}-kubeconfig.yaml"
}
Here I fixed the "local.cheapest_metro_price is null" issue during CI plan.
terraform.tfvars.example
## -- Harvester version to be installed (Must be a valid version tag from https://github.com/rancherlabs/terraform-harvester-equinix/tree/main/ipxe)
harvester_version = "v1.3.1"
## -- Number of nodes to deploy Harvester cluster
node_count = 3
## -- Create a Metal Project if this is 'true'. Else use provided 'project_name'
metal_create_project = false
## -- Name of the Equinix Metal project to deploy into, when not looking up by project_id
project_name = "Harvester Labs"
## -- Equinix Metal organization ID to create or find a project in
organization_id = ""
## -- Equinix Metal project ID to deploy into, if not creating a new project or looking up by nam
project_id = ""
## -- Size of the servers to be deployed on Equinix metal (https://deploy.equinix.com/developers/docs/metal/hardware/standard-servers/)
plan = "m3.small.x86"
## -- Equinix metal billing/invoice generation schedule (hourly/daily/monthly/yearly)
billing_cycle = "hourly"
## -- Equinix metal data center location (https://deploy.equinix.com/developers/docs/metal/locations/metros/). Examples: SG,SV,AM,MA,Ny,LA,etc.
metro = "SG"
## -- URL to the iPXE script to use for booting the server (harvester_version will be appended to this without the 'v' prefix)
ipxe_script = "https://raw.githubusercontent.com/rancherlabs/terraform-harvester-equinix/main/ipxe/ipxe-"
## -- Prefix for resources to be created in equinix metal
hostname_prefix = "harvester-pxe"
## -- Set to true to use spot instance instead of on demand. Also set your max bid price if true.
spot_instance = true
## -- Maximum bid price for spot request
max_bid_price = "0.75"
## -- A boolean variable to control cheapest metro selection
use_cheapest_metro = true
## -- Your ssh key, examples: 'github: myghid' or 'ssh-rsa AAAAblahblah== keyname'
ssh_key = ""
## -- Number of VLANs to be created
num_of_vlans = 2
## -- Rancher API endpoint to manager your Harvester cluster
rancher_api_url = ""
## -- Rancher access key
rancher_access_key = ""
## -- Rancher secret key
rancher_secret_key = ""
## -- Allow insecure connections to the Rancher API
rancher_insecure = false
## -- Equinix Metal authentication token. Required when using Spot Instances for HTTP pricing lookups. METAL_AUTH_TOKEN should always be set as an environment variable
api_key = ""
Rewritten.
README.md
# Harvester on Equinix
Simple example using the terraform equinix provider to create a multi node harvester cluster.
## How to create resources
- Copy `./terraform.tfvars.example` to `./terraform.tfvars`
- Edit `./terraform.tfvars`
- Update the required variables:
- `project_name` to identify project in your Equinix account <- **otherwise you can export the `TF_VAR_project_name` or `TF_VAR_project_id` variable**
- `hostname_prefix` to give the resources an identifiable name (eg, your initials or first name)
- `ssh_key` to access the nodes
- `api_key` to access your Equinix account <- **otherwise you can export the `METAL_AUTH_TOKEN` or `TF_VAR_api_key` variable**
#### Optionally the user can also provide:
`TF_VAR_metal_create_project` Terraform variable to create a project of name `TF_VAR_project_name` if it does not exist.
#### Terraform Apply
\`\`\`bash
terraform init -upgrade && terraform apply -auto-approve
\`\`\`
#### Terraform Destroy
- Destroy the resources when finished
\`\`\`bash
terraform destroy -auto-approve
\`\`\`
The Harvester console can be accessed using an Elastic IP created by the sample.
A random token and password will be generated for your example.
\`\`\`sh
terraform output -raw harvester_os_password
terraform output -raw harvester_cluster_secret
\`\`\`
If you provide a Rancher API URL and keys, your Harvester environment can be managed by Rancher and a kubeconfig file will be saved locally.
Rewritten. I added the backticks for the terraform commands because otherwise the copy/paste here won't work; obviously they must be removed.
docs.md
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.2 |
| <a name="requirement_equinix"></a> [equinix](#requirement\_equinix) | 2.3.2 |
| <a name="requirement_rancher2"></a> [rancher2](#requirement\_rancher2) | 5.0.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_equinix"></a> [equinix](#provider\_equinix) | 2.3.2 |
| <a name="provider_http"></a> [http](#provider\_http) | n/a |
| <a name="provider_local"></a> [local](#provider\_local) | n/a |
| <a name="provider_rancher2"></a> [rancher2](#provider\_rancher2) | 5.0.0 |
| <a name="provider_random"></a> [random](#provider\_random) | n/a |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [equinix_metal_device.join](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_device) | resource |
| [equinix_metal_device.seed](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_device) | resource |
| [equinix_metal_ip_attachment.first_address_assignment](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_ip_attachment) | resource |
| [equinix_metal_port_vlan_attachment.vlan_attach_join](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_port_vlan_attachment) | resource |
| [equinix_metal_port_vlan_attachment.vlan_attach_seed](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_port_vlan_attachment) | resource |
| [equinix_metal_project.new_project](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_project) | resource |
| [equinix_metal_reserved_ip_block.harvester_vip](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_reserved_ip_block) | resource |
| [equinix_metal_spot_market_request.join_spot_request](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_spot_market_request) | resource |
| [equinix_metal_spot_market_request.seed_spot_request](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_spot_market_request) | resource |
| [equinix_metal_vlan.vlans](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/resources/metal_vlan) | resource |
| [local_file.harvester_kubeconfig](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [rancher2_cluster.rancher_cluster](https://registry.terraform.io/providers/rancher/rancher2/5.0.0/docs/resources/cluster) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_password.token](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [equinix_metal_device.join_devices](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_device) | data source |
| [equinix_metal_device.seed_device](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_device) | data source |
| [equinix_metal_ip_block_ranges.address_block](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_ip_block_ranges) | data source |
| [equinix_metal_project.project](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_project) | data source |
| [equinix_metal_spot_market_request.join_req](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_spot_market_request) | data source |
| [equinix_metal_spot_market_request.seed_req](https://registry.terraform.io/providers/equinix/equinix/2.3.2/docs/data-sources/metal_spot_market_request) | data source |
| [http_http.prices](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_api_key"></a> [api\_key](#input\_api\_key) | Equinix Metal authentication token. Required when using Spot Instances for HTTP pricing lookups. METAL\_AUTH\_TOKEN should always be set as an environment variable | `string` | `""` | no |
| <a name="input_billing_cycle"></a> [billing\_cycle](#input\_billing\_cycle) | Equinix metal billing/invoice generation schedule (hourly/daily/monthly/yearly) | `string` | `"hourly"` | no |
| <a name="input_harvester_version"></a> [harvester\_version](#input\_harvester\_version) | Harvester version to be installed (Must be a valid version tag from https://github.com/rancherlabs/terraform-harvester-equinix/tree/main/ipxe) | `string` | `"v1.3.1"` | no |
| <a name="input_hostname_prefix"></a> [hostname\_prefix](#input\_hostname\_prefix) | Prefix for resources to be created in equinix metal | `string` | `"harvester-pxe"` | no |
| <a name="input_ipxe_script"></a> [ipxe\_script](#input\_ipxe\_script) | URL to the iPXE script to use for booting the server (harvester\_version will be appended to this without the 'v' prefix) | `string` | `"https://raw.githubusercontent.com/rancherlabs/terraform-harvester-equinix/main/ipxe/ipxe-"` | no |
| <a name="input_max_bid_price"></a> [max\_bid\_price](#input\_max\_bid\_price) | Maximum bid price for spot request | `string` | `"0.75"` | no |
| <a name="input_metal_create_project"></a> [metal\_create\_project](#input\_metal\_create\_project) | Create a Metal Project if this is 'true'. Else use provided 'project\_name' | `bool` | `false` | no |
| <a name="input_metro"></a> [metro](#input\_metro) | Equinix metal data center location (https://deploy.equinix.com/developers/docs/metal/locations/metros/). Examples: SG,SV,AM,MA,Ny,LA,etc. | `string` | `"SG"` | no |
| <a name="input_node_count"></a> [node\_count](#input\_node\_count) | Number of nodes to deploy Harvester cluster | `number` | `3` | no |
| <a name="input_num_of_vlans"></a> [num\_of\_vlans](#input\_num\_of\_vlans) | Number of VLANs to be created | `number` | `2` | no |
| <a name="input_organization_id"></a> [organization\_id](#input\_organization\_id) | Equinix Metal organization ID to create or find a project in | `string` | `""` | no |
| <a name="input_plan"></a> [plan](#input\_plan) | Size of the servers to be deployed on Equinix metal (https://deploy.equinix.com/developers/docs/metal/hardware/standard-servers/) | `string` | `"m3.small.x86"` | no |
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | Equinix Metal project ID to deploy into, if not creating a new project or looking up by name | `string` | `""` | no |
| <a name="input_project_name"></a> [project\_name](#input\_project\_name) | Name of the Equinix Metal project to deploy into, when not looking up by project\_id | `string` | `"Harvester Labs"` | no |
| <a name="input_rancher_access_key"></a> [rancher\_access\_key](#input\_rancher\_access\_key) | Rancher access key | `string` | `""` | no |
| <a name="input_rancher_api_url"></a> [rancher\_api\_url](#input\_rancher\_api\_url) | Rancher API endpoint to manager your Harvester cluster | `string` | `""` | no |
| <a name="input_rancher_insecure"></a> [rancher\_insecure](#input\_rancher\_insecure) | Allow insecure connections to the Rancher API | `bool` | `false` | no |
| <a name="input_rancher_secret_key"></a> [rancher\_secret\_key](#input\_rancher\_secret\_key) | Rancher secret key | `string` | `""` | no |
| <a name="input_spot_instance"></a> [spot\_instance](#input\_spot\_instance) | Set to true to use spot instance instead of on demand. Also set your max bid price if true. | `bool` | `true` | no |
| <a name="input_ssh_key"></a> [ssh\_key](#input\_ssh\_key) | Your ssh key, examples: 'github: myghid' or 'ssh-rsa AAAAblahblah== keyname' | `string` | `""` | no |
| <a name="input_use_cheapest_metro"></a> [use\_cheapest\_metro](#input\_use\_cheapest\_metro) | A boolean variable to control cheapest metro selection | `bool` | `true` | no |
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_harvester_cluster_secret"></a> [harvester\_cluster\_secret](#output\_harvester\_cluster\_secret) | The cluster secret for joining nodes to the cluster (https://docs.harvesterhci.io/v1.3/install/harvester-configuration/#token) |
| <a name="output_harvester_os_password"></a> [harvester\_os\_password](#output\_harvester\_os\_password) | The password for the default OS user, 'rancher' (https://docs.harvesterhci.io/v1.3/install/harvester-configuration/#ospassword) |
| <a name="output_harvester_url"></a> [harvester\_url](#output\_harvester\_url) | The URL to reach the Harvester user interface |
| <a name="output_out_of_band_hostnames"></a> [out\_of\_band\_hostnames](#output\_out\_of\_band\_hostnames) | Out of band hostnames for SSH access to the console |
| <a name="output_public_ips"></a> [public\_ips](#output\_public\_ips) | The public IP addresses of all Harvester nodes |
New file.
Everything worked fine using this terraform.tfvars file:
glovecchio ~ suse displague terraform-harvester-equinix fix/sans_spot cat terraform.tfvars
project_name = "Harvester Labs"
metro = "AM"
hostname_prefix = "glovecchio-harv"
ssh_key = "ssh-rsa MYKEY="
api_key = "MYKEY"
glovecchio ~ suse displague terraform-harvester-equinix fix/sans_spot
If you give me a chance to contribute in the "[email protected]:displague/terraform-harvester-equinix.git" repo, I'll send you everything, otherwise please take a look at the above and tell me what you think.
Thanks again for the help!
d5b9be1
to
c55c4f8
Compare
@glovecchi0 I applied your changes in the latest commit (with minor formatting tweaks and --author you). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@glovecchi0 do you have the option to flip the workflow approval switch so CI will run checks? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The terraform plan
check is still failing and needs to be fixed before merging. See https://github.com/rancherlabs/terraform-harvester-equinix/actions/runs/10831569903/job/30155965468?pr=93
Hey @dnoland1,
I don't encounter any errors and the only thing I do is export the METAL_AUTH_TOKEN variable. PS: the api_key variable cannot work, as it is not initialized in the provider.tf file. |
The api_key is used for the spot market pricing requests issued by the http provider (a feature not present in the Equinix TF provider). |
@dnoland1 the CI failed because my PR is from a fork, it does not have access to the project's secrets. The error, as follows, is sensible under root org executions where It may improve the contributor experience if the non-sensitive variables were moved to an environment variable (not secret) and made part of a CI build that only executes
|
I put in a PR to hard code the project name in the GH action instead of using a secret. |
PR is now merged. @displague if you want to update your PR/branch with the latest from main we can see if it passes the GH action checks. |
Signed-off-by: Marques Johansson <[email protected]>
ec5b209
to
53ee85b
Compare
Tests still aren't passing because it cannot retrieve the project id using the project name because the Equinix API key is not available. I'll merge and will need to make sure future internal PRs pass the tests. |
While attempting to deploy, I noticed a few things that have been addressed in this PR.
I would like someone more familiar with the project to review these changes and ensure that deployment is still working as expected. With these changes, I did get a successful
terraform apply
, and after a few minutes, I was able to access the Harvester portal.project_id
variablespot_instance
was false. These pricing lookups will be skipped when not requested. Additionally, the use_cheapest_metro value was overriding the user suppliedmetro
value whenspot_instance
was false. This has been corrected.organization_id
variable added as it may be required when creating projects and multiple Equinix Metal organizations are availableharvester_os_password
sensitive output variable added for chaining this module to additional modules where harvester credentials may be needed (also helpful for logging into the UI without looking through terraform state)harvester_cluster_secret
sensitive output variable added for chaining this module to additional modules where harvester credentials may be needed