mirror of
https://github.com/oscarhermoso/terraform-provider-binarylane
synced 2026-10-20 05:56:05 +11:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1b7b9853e |
+1
-1
@@ -30,4 +30,4 @@ tmp
|
||||
# Normally, you wouldn't want to exclude lock files, but in this case, we're
|
||||
# using Terraform's lock file to store the provider version, so we need to
|
||||
# ignore it.
|
||||
terraform.lock.hcl
|
||||
.terraform.lock.hcl
|
||||
|
||||
@@ -24,6 +24,7 @@ TODO
|
||||
- `backups` (Boolean) If true this will enable two daily backups for the server. Options.daily_backups will override this value if provided. Setting this to false has no effect.
|
||||
- `name` (String) The hostname of your server, such as vps01.yourcompany.com. If not provided, the server will be created with a random name.
|
||||
- `password` (String) If this is provided the specified or default remote user's account password will be set to this value. Only valid if the server supports password change actions (check server.password_change_supported via the servers endpoint). If omitted and the server supports password change actions a random password will be generated and emailed to the account email address.
|
||||
- `user_data` (String) If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.
|
||||
|
||||
### Read-Only
|
||||
|
||||
|
||||
@@ -27,3 +27,4 @@ Provides a Binary Lane Server resource. This can be used to create and delete se
|
||||
- `id` (Number) The ID of the server to fetch.
|
||||
- `name` (String) The hostname of your server, such as vps01.yourcompany.com. If not provided, the server will be created with a random name.
|
||||
- `password` (String, Sensitive) If this is provided the specified or default remote user's account password will be set to this value. Only valid if the server supports password change actions (check server.password_change_supported via the servers endpoint). If omitted and the server supports password change actions a random password will be generated and emailed to the account email address.
|
||||
- `user_data` (String) If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# .tfstate files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
# Ignore transient lock info files created by terraform apply
|
||||
.terraform.tfstate.lock.info
|
||||
|
||||
# Include override files you do wish to add to version control using negated pattern
|
||||
# !example_override.tf
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
# example: *tfplan*
|
||||
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
# Misc
|
||||
|
||||
# Don't commit private keys
|
||||
id_ed25519
|
||||
@@ -0,0 +1,47 @@
|
||||
# examples/cloud-init
|
||||
|
||||
Binary lane servers initialize cloud-init configurations to the server upon creation.
|
||||
|
||||
If you want to deploy multiple parts of a cloud-init configuration, you can use the [cloudinit_config](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) data source.
|
||||
|
||||
```terraform
|
||||
terraform {
|
||||
required_providers {
|
||||
binarylane = {
|
||||
source = "oscarhermoso/binarylane"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "binarylane" {
|
||||
# api_url = "" # Defaults to "https://api.binarylane.com"
|
||||
# api_token = "" # Recommend setting with environment variable BINARYLANE_API_TOKEN
|
||||
}
|
||||
|
||||
data "cloudinit_config" "example" {
|
||||
gzip = false
|
||||
base64_encode = false
|
||||
|
||||
part {
|
||||
filename = "hello-script.sh"
|
||||
content_type = "text/x-shellscript"
|
||||
|
||||
content = file("./hello-script.sh")
|
||||
}
|
||||
|
||||
part {
|
||||
filename = "cloud-config.yaml"
|
||||
content_type = "text/cloud-config"
|
||||
|
||||
content = file("./cloud-config.yml")
|
||||
}
|
||||
}
|
||||
|
||||
resource "binarylane_server" "example" {
|
||||
name = "tf-nix-example"
|
||||
region = "per"
|
||||
image = "ubuntu-24.04"
|
||||
size = "std-min"
|
||||
user_data = data.cloudinit_config.example.rendered
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
#cloud-config
|
||||
runcmd:
|
||||
- echo "Hello World" > /var/tmp/output.txt
|
||||
@@ -0,0 +1,20 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
binarylane = {
|
||||
source = "oscarhermoso/binarylane"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "binarylane" {
|
||||
# api_url = "" # Defaults to "https://api.binarylane.com"
|
||||
# api_token = "" # Recommend setting with environment variable BINARYLANE_API_TOKEN
|
||||
}
|
||||
|
||||
resource "binarylane_server" "example" {
|
||||
name = "tf-cloud-init-example"
|
||||
region = "per"
|
||||
image = "ubuntu-24.04"
|
||||
size = "std-min"
|
||||
user_data = file("./cloud-config.yml")
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# .tfstate files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
# Ignore transient lock info files created by terraform apply
|
||||
.terraform.tfstate.lock.info
|
||||
|
||||
# Include override files you do wish to add to version control using negated pattern
|
||||
# !example_override.tf
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
# example: *tfplan*
|
||||
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
# Misc
|
||||
|
||||
# Don't commit private keys
|
||||
id_ed25519
|
||||
@@ -0,0 +1,3 @@
|
||||
# examples/nix
|
||||
|
||||
WIP
|
||||
@@ -0,0 +1,14 @@
|
||||
#cloud-config
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/canonical/cloud-init/main/cloudinit/config/schemas/schema-cloud-config-v1.json
|
||||
|
||||
#cloud-config
|
||||
write_files:
|
||||
- path: /etc/nixos/host.nix
|
||||
permissions: "0644"
|
||||
content: |
|
||||
{pkgs, ...}:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [ vim ];
|
||||
}
|
||||
runcmd:
|
||||
- curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-23.05 bash 2>&1 | tee /var/tmp/infect.log
|
||||
@@ -0,0 +1,20 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
binarylane = {
|
||||
source = "oscarhermoso/binarylane"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "binarylane" {
|
||||
# api_url = "" # Defaults to "https://api.binarylane.com"
|
||||
# api_token = "" # Recommend setting with environment variable BINARYLANE_API_TOKEN
|
||||
}
|
||||
|
||||
resource "binarylane_server" "example" {
|
||||
name = "tf-nix-example"
|
||||
region = "per"
|
||||
image = "debian-12"
|
||||
size = "std-min"
|
||||
user_data = file("./cloud-config.yml")
|
||||
}
|
||||
@@ -3,12 +3,12 @@ package provider
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"terraform-provider-binarylane/internal/resources"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
d_schema "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
|
||||
// Ensure the implementation satisfies the expected interfaces.
|
||||
@@ -70,7 +70,9 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
return
|
||||
}
|
||||
|
||||
// Read API call logic
|
||||
// TODO: Use go routines here to make requests concurrently
|
||||
|
||||
// Read server
|
||||
serverResp, err := d.bc.client.GetServersServerIdWithResponse(ctx, data.Id.ValueInt64())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError(
|
||||
@@ -79,23 +81,40 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
)
|
||||
return
|
||||
}
|
||||
if serverResp.StatusCode() != http.StatusOK {
|
||||
resp.Diagnostics.AddError(
|
||||
fmt.Sprintf("Unexpected HTTP status code reading server: name=%s", data.Id.String()),
|
||||
fmt.Sprintf("Unexpected HTTP status code reading server: %s", serverResp.Body),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Fetch user data
|
||||
|
||||
// Read user data
|
||||
// userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
|
||||
// if err != nil {
|
||||
// resp.Diagnostics.AddError(
|
||||
// fmt.Sprintf("Error reading server user data: name=%s", data.Id.String()),
|
||||
// err.Error(),
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
// if userDataResp.StatusCode() != http.StatusOK {
|
||||
// resp.Diagnostics.AddError(
|
||||
// fmt.Sprintf("Unexpected HTTP status code reading server user data: name=%s", data.Id.String()),
|
||||
// fmt.Sprintf("Unexpected HTTP status code reading server user data: %s", serverResp.Body),
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
|
||||
// Set data values
|
||||
tflog.Trace(ctx,
|
||||
fmt.Sprintf(
|
||||
"Reading server: id=%d, name=%s, image=%s, region=%s, size=%s",
|
||||
*serverResp.JSON200.Server.Id,
|
||||
*serverResp.JSON200.Server.Name,
|
||||
*serverResp.JSON200.Server.Image.Slug,
|
||||
*serverResp.JSON200.Server.Region.Slug,
|
||||
*serverResp.JSON200.Server.Size.Slug,
|
||||
),
|
||||
)
|
||||
data.Id = types.Int64Value(*serverResp.JSON200.Server.Id)
|
||||
data.Name = types.StringValue(*serverResp.JSON200.Server.Name)
|
||||
data.Image = types.StringValue(*serverResp.JSON200.Server.Image.Slug)
|
||||
data.Region = types.StringValue(*serverResp.JSON200.Server.Region.Slug)
|
||||
data.Size = types.StringValue(*serverResp.JSON200.Server.Size.Slug)
|
||||
// data.UserData = types.StringValue(*userDataResp.JSON200.UserData)
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
@@ -74,6 +76,17 @@ func (r *serverResource) Schema(ctx context.Context, _ resource.SchemaRequest, r
|
||||
Computed: backups.IsOptional(),
|
||||
Default: booldefault.StaticBool(false), // Add default to backups
|
||||
}
|
||||
|
||||
user_data := resp.Schema.Attributes["user_data"]
|
||||
resp.Schema.Attributes["user_data"] = &schema.StringAttribute{
|
||||
Description: user_data.GetDescription(),
|
||||
MarkdownDescription: user_data.GetMarkdownDescription(),
|
||||
Optional: user_data.IsComputed(),
|
||||
Computed: user_data.IsOptional(),
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
@@ -90,10 +103,11 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest,
|
||||
tflog.Debug(ctx, fmt.Sprintf("Creating server: name=%s", data.Name.ValueString()))
|
||||
|
||||
body := binarylane.CreateServerRequest{
|
||||
Name: data.Name.ValueStringPointer(),
|
||||
Image: data.Image.ValueString(),
|
||||
Region: data.Region.ValueString(),
|
||||
Size: data.Size.ValueString(),
|
||||
Name: data.Name.ValueStringPointer(),
|
||||
Image: data.Image.ValueString(),
|
||||
Region: data.Region.ValueString(),
|
||||
Size: data.Size.ValueString(),
|
||||
UserData: data.UserData.ValueStringPointer(),
|
||||
}
|
||||
|
||||
if data.Password.IsNull() {
|
||||
|
||||
@@ -18,6 +18,10 @@ resource "binarylane_server" "test" {
|
||||
region = "per"
|
||||
image = "ubuntu-24.04"
|
||||
size = "std-min"
|
||||
user_data = <<EOT
|
||||
#cloud-config
|
||||
echo "Hello World" > /var/tmp/output.txt
|
||||
EOT
|
||||
}
|
||||
|
||||
data "binarylane_server" "test" {
|
||||
@@ -32,6 +36,9 @@ data "binarylane_server" "test" {
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "region", "per"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "image", "ubuntu-24.04"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "size", "std-min"),
|
||||
resource.TestCheckResourceAttr("binarylane_server.test", "user_data", `#cloud-config
|
||||
echo "Hello World" > /var/tmp/output.txt
|
||||
`),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server.test", "id"),
|
||||
|
||||
// Verify data source values
|
||||
@@ -40,6 +47,10 @@ data "binarylane_server" "test" {
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "image", "ubuntu-24.04"),
|
||||
resource.TestCheckResourceAttr("data.binarylane_server.test", "size", "std-min"),
|
||||
resource.TestCheckResourceAttrSet("data.binarylane_server.test", "id"),
|
||||
// resource.TestCheckResourceAttr("data.binarylane_server.test", "user_data", `
|
||||
// #cloud-config
|
||||
// echo "Hello World" > /var/tmp/output.txt
|
||||
// `),
|
||||
),
|
||||
},
|
||||
// ImportState testing
|
||||
|
||||
@@ -59,6 +59,15 @@ func ServerResourceSchema(ctx context.Context) schema.Schema {
|
||||
stringvalidator.LengthAtLeast(1),
|
||||
},
|
||||
},
|
||||
"user_data": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Description: "If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.",
|
||||
MarkdownDescription: "If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.",
|
||||
Validators: []validator.String{
|
||||
stringvalidator.LengthAtMost(65536),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -71,4 +80,5 @@ type ServerModel struct {
|
||||
Password types.String `tfsdk:"password"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Size types.String `tfsdk:"size"`
|
||||
UserData types.String `tfsdk:"user_data"`
|
||||
}
|
||||
|
||||
@@ -73,6 +73,25 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "user_data",
|
||||
"string": {
|
||||
"computed_optional_required": "computed_optional",
|
||||
"description": "If provided this will be used to initialise the new server. This must be left null if the Image does not support UserData, see DistributionInfo.Features for more information.",
|
||||
"validators": [
|
||||
{
|
||||
"custom": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
}
|
||||
],
|
||||
"schema_definition": "stringvalidator.LengthAtMost(65536)"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"int64": {
|
||||
|
||||
@@ -57,7 +57,6 @@ resources:
|
||||
- server
|
||||
- ssh_keys
|
||||
- vpc_id
|
||||
- user_data
|
||||
- port_blocking
|
||||
ssh_key:
|
||||
create:
|
||||
|
||||
Reference in New Issue
Block a user