Skip to content
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

feat(baremetal): custom partitionning #2820

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
148 changes: 148 additions & 0 deletions internal/services/baremetal/partition_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package baremetal

import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

func PartitioningSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Description: "Configuration for partitioning schema.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"disks": {
Type: schema.TypeList,
Optional: true,
Description: "List of disks with partitions.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"device": {
Type: schema.TypeString,
Required: true,
Description: "Device name (e.g., /dev/nvme0n1).",
},
"partitions": {
Type: schema.TypeList,
Optional: true,
Description: "Partitions for the disk.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"label": {
Type: schema.TypeString,
Required: true,
Description: "Partition label.",
},
"number": {
Type: schema.TypeInt,
Required: true,
Description: "Partition number.",
},
"size": {
Type: schema.TypeInt,
Required: true,
Description: "Partition size in bytes.",
},
},
},
},
},
},
},
"raids": {
Type: schema.TypeList,
Optional: true,
Description: "RAID configurations.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the RAID device.",
},
"level": {
Type: schema.TypeString,
Required: true,
Description: "RAID level.",
},
"devices": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "Devices in the RAID.",
},
},
},
},
"filesystems": {
Type: schema.TypeList,
Optional: true,
Description: "Filesystem configurations.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"device": {
Type: schema.TypeString,
Required: true,
Description: "Device name for the filesystem.",
},
"format": {
Type: schema.TypeString,
Required: true,
Description: "Filesystem format.",
},
"mountpoint": {
Type: schema.TypeString,
Required: true,
Description: "Mountpoint for the filesystem.",
},
},
},
},
"zfs": {
Type: schema.TypeList,
Optional: true,
Description: "ZFS configurations.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"pools": {
Type: schema.TypeList,
Optional: true,
Description: "List of ZFS pools.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the ZFS pool.",
},
"type": {
Type: schema.TypeString,
Required: true,
Description: "Type of the ZFS pool (e.g., mirror, raidz).",
},
"devices": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "Devices in the ZFS pool.",
},
"options": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "Options for the ZFS pool.",
},
},
},
},
},
},
},
},
},
}
}
24 changes: 23 additions & 1 deletion internal/services/baremetal/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package baremetal

import (
"context"
"encoding/json"
"fmt"

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
Expand Down Expand Up @@ -255,7 +255,13 @@ If this behaviour is wanted, please set 'reinstall_on_ssh_key_changes' argument
},
},
},
"partitioning": {
Type: schema.TypeString,
Optional: true,
Description: "The path to the patitioning json file",
},
},

CustomizeDiff: customdiff.Sequence(
cdf.LocalityCheck("private_network.#.id"),
customDiffPrivateNetworkOption(),
Expand Down Expand Up @@ -319,13 +325,29 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m interfa
}
}

partitioningSchema := baremetal.Schema{}
if file, ok := d.GetOk("partitioning"); ok {
todecode, _ := json.Marshal(file)
err = json.Unmarshal(todecode, &partitioningSchema)
}

serverRequestInstall := baremetal.CreateServerRequestInstall{
OsID: zonal.ExpandID(d.Get("os")).ID,
Hostname: d.Get("hostname").(string),
SSHKeyIDs: types.ExpandStrings(d.Get("ssh_key_ids")),
User: types.ExpandStringPtr(d.Get("user")),
Password: types.ExpandStringPtr(d.Get("password")),
PartitioningSchema: &partitioningSchema,
}

server, err := api.CreateServer(&baremetal.CreateServerRequest{
Zone: zone,
Name: types.ExpandOrGenerateString(d.Get("name"), "bm"),
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
Description: d.Get("description").(string),
OfferID: offerID.ID,
Tags: types.ExpandStrings(d.Get("tags")),
Install: &serverRequestInstall,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
Expand Down
102 changes: 99 additions & 3 deletions internal/services/baremetal/server_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package baremetal_test

import (
"encoding/json"
"fmt"
"regexp"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand All @@ -16,8 +18,9 @@ import (

const SSHKeyBaremetal = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM7HUxRyQtB2rnlhQUcbDGCZcTJg7OvoznOiyC9W6IxH [email protected]"

var jsonConfigPartitioning = "{\"disks\":[{\"device\":\"/dev/nvme0n1\",\"partitions\":[{\"label\":\"uefi\",\"number\":1,\"size\":536870912},{\"label\":\"swap\",\"number\":2,\"size\":4294967296},{\"label\":\"boot\",\"number\":3,\"size\":1073741824},{\"label\":\"root\",\"number\":4,\"size\":1017827045376}]},{\"device\":\"/dev/nvme1n1\",\"partitions\":[{\"label\":\"swap\",\"number\":1,\"size\":4294967296},{\"label\":\"boot\",\"number\":2,\"size\":1073741824},{\"label\":\"root\",\"number\":3,\"size\":1017827045376}]}],\"filesystems\":[{\"device\":\"/dev/nvme0n1p1\",\"format\":\"fat32\",\"mountpoint\":\"/boot/efi\"},{\"device\":\"/dev/md0\",\"format\":\"ext4\",\"mountpoint\":\"/boot\"},{\"device\":\"/dev/md1\",\"format\":\"ext4\",\"mountpoint\":\"/\"}],\"raids\":[{\"devices\":[\"/dev/nvme0n1p3\",\"/dev/nvme1n1p2\"],\"level\":\"raid_level_1\",\"name\":\"/dev/md0\"},{\"devices\":[\"/dev/nvme0n1p4\",\"/dev/nvme1n1p3\"],\"level\":\"raid_level_1\",\"name\":\"/dev/md1\"}],\"zfs\":{\"pools\":[]}}"

func TestAccServer_Basic(t *testing.T) {
// t.Skip("Skipping Baremetal Server test as no stock is available currently")
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
if !IsOfferAvailable(OfferID, Zone, tt) {
Expand Down Expand Up @@ -51,7 +54,7 @@ func TestAccServer_Basic(t *testing.T) {
description = "test a description"
offer = "%s"
os = data.scaleway_baremetal_os.my_os.os_id

tags = [ "terraform-test", "scaleway_baremetal_server", "minimal" ]
ssh_key_ids = [ scaleway_iam_ssh_key.main.id ]
}
Expand Down Expand Up @@ -86,7 +89,7 @@ func TestAccServer_Basic(t *testing.T) {
name = "%s"
zone = "fr-par-1"
description = "test a description"
offer = "%s"
offer = %s
os = data.scaleway_baremetal_os.my_os.os_id

tags = [ "terraform-test", "scaleway_baremetal_server", "minimal", "edited" ]
Expand Down Expand Up @@ -172,6 +175,65 @@ func TestAccServer_WithoutInstallConfig(t *testing.T) {
})
}

func TestAccServer_CreateServerWithCustomInstallConfig(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
if !IsOfferAvailable(OfferID, Zone, tt) {
t.Skip("Offer is out of stock")
}

SSHKeyName := "TestAccServer_CreateServerWithCustomInstallConfig"
name := "TestAccServer_CreateServerWithCustomInstallConfig"
//fileName := "partitioning.json"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: baremetalchecks.CheckServerDestroy(tt),
Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
data "scaleway_baremetal_os" "my_os" {
zone = "fr-par-1"
name = "Ubuntu"
version = "22.04 LTS (Jammy Jellyfish)"
}

resource "scaleway_iam_ssh_key" "main" {
name = "%s"
public_key = "%s"
}

resource "scaleway_baremetal_server" "base" {
name = "%s"
zone = "fr-par-1"
description = "test a description"
offer = "%s"
os = data.scaleway_baremetal_os.my_os.os_id
partitioning = "%s"

tags = [ "terraform-test", "scaleway_baremetal_server", "minimal" ]
ssh_key_ids = [ scaleway_iam_ssh_key.main.id ]
}
`, SSHKeyName, SSHKeyBaremetal, name, OfferName, strings.ReplaceAll(jsonConfigPartitioning, "\"", "\\\"")),
Check: resource.ComposeTestCheckFunc(
testAccCheckBaremetalServerExists(tt, "scaleway_baremetal_server.base"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "name", name),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "offer_id", "fr-par-1/206ea234-9097-4ae1-af68-6d2be09f47ed"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "os", "fr-par-1/96e5f0f2-d216-4de2-8a15-68730d877885"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "description", "test a description"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "tags.0", "terraform-test"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "tags.1", "scaleway_baremetal_server"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "tags.2", "minimal"),
testAccChechPartitioning(tt, "scaleway_baremetal_server.base", "partitioning_schema.disks.0.partition.0.size", "536870912", jsonConfigPartitioning),
//resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "install.partitioning_schema.disks.0.partition.0.size", "536870912"),
acctest.CheckResourceAttrUUID("scaleway_baremetal_server.base", "ssh_key_ids.0"),
),
},
},
})
}

func TestAccServer_CreateServerWithOption(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
Expand Down Expand Up @@ -992,6 +1054,40 @@ func testAccCheckBaremetalServerExists(tt *acctest.TestTools, n string) resource
}
}

func testAccChechPartitioning(tt *acctest.TestTools, n string, key string, value string, source string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("resource not found: %s", n)
}
baremetalAPI, zonedID, err := baremetal.NewAPIWithZoneAndID(tt.Meta, rs.Primary.ID)
if err != nil {
return err
}

server, err := baremetalAPI.GetServer(&baremetalSDK.GetServerRequest{
ServerID: zonedID.ID,
Zone: zonedID.Zone,
})
if err != nil {
return err
}
if server.Install.PartitioningSchema == nil {
return fmt.Errorf("server %s has no partitioning schema", n)
}
var schema baremetalSDK.Schema
//partitioning, _ := json.Marshal(source)
err = json.Unmarshal([]byte(source), &schema)
if err != nil {
return err
}
if &schema != server.Install.PartitioningSchema {
return fmt.Errorf("server %s has not custom partitioning install", n)
}
return nil
}
}

func testAccCheckBaremetalServerHasOptions(tt *acctest.TestTools, n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down
Loading
Loading