From 7aa4f20e4a01410fc1745fdadfe9969fb7e2d025 Mon Sep 17 00:00:00 2001 From: Laure-di Date: Thu, 27 Nov 2025 11:31:34 +0100 Subject: [PATCH 1/4] feat(baremetal): handle file cloud-init bump sdk-go --- internal/services/baremetal/server.go | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/internal/services/baremetal/server.go b/internal/services/baremetal/server.go index ac572a37a2..8a9cbf4b40 100644 --- a/internal/services/baremetal/server.go +++ b/internal/services/baremetal/server.go @@ -2,8 +2,11 @@ package baremetal import ( "context" + "encoding/base64" "encoding/json" + "errors" "fmt" + "os" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -297,6 +300,13 @@ If this behaviour is wanted, please set 'reinstall_on_ssh_key_changes' argument }, }, }, + "cloud_init": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Configuration data to pass to cloud-init such as a YAML cloud config data or a user-data script", + ValidateFunc: validation.StringLenBetween(0, 127998), + }, }, CustomizeDiff: customdiff.Sequence( customDiffOffer(), @@ -367,6 +377,14 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di Protected: d.Get("protected").(bool), } + if cloudInit, ok := d.GetOk("cloud_init"); ok { + userData, err := LoadUserDataBase64(cloudInit) + if err != nil { + return diag.FromErr(err) + } + req.UserData = &userData + } + partitioningSchema := baremetal.Schema{} if file, ok := d.GetOk("partitioning"); ok || !d.Get("install_config_afterward").(bool) { @@ -457,6 +475,21 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di return ResourceServerRead(ctx, d, m) } +func LoadUserDataBase64(cloudInit interface{}) ([]byte, error) { + value := cloudInit.(string) + var content []byte + if data, err := os.ReadFile(value); errors.Is(err, os.ErrNotExist) { + content = []byte(value) + } else if err == nil { + content = data + } else { + return nil, err + } + encoded := base64.StdEncoding.EncodeToString(content) + userData := []byte(encoded) + return userData, nil +} + func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { api, zonedID, err := NewAPIWithZoneAndID(m, d.Id()) if err != nil { @@ -514,6 +547,7 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m any) diag _ = d.Set("ipv4", flattenIPv4s(server.IPs)) _ = d.Set("ipv6", flattenIPv6s(server.IPs)) _ = d.Set("protected", server.Protected) + _ = d.Set("cloud_init", server.UserData) if server.Install != nil { _ = d.Set("os", zonal.NewIDString(server.Zone, os.ID)) @@ -696,6 +730,16 @@ func ResourceServerUpdate(ctx context.Context, d *schema.ResourceData, m any) di hasChanged := false + if d.HasChange("cloud_init") { + cloudInit := d.Get("cloud_init").(string) + userData, err := LoadUserDataBase64(cloudInit) + if err != nil { + return diag.FromErr(err) + } + req.UserData = &userData + hasChanged = true + } + if d.HasChange("name") { req.Name = types.ExpandUpdatedStringPtr(d.Get("name")) hasChanged = true From 269a444799ec529fb2727a9084a492d700c1710d Mon Sep 17 00:00:00 2001 From: Laure-di Date: Thu, 27 Nov 2025 12:44:33 +0100 Subject: [PATCH 2/4] doc(baremetal): add cloud-init attribut and example --- docs/resources/baremetal_server.md | 55 ++++++++++++++++++++ templates/resources/baremetal_server.md.tmpl | 55 ++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/docs/resources/baremetal_server.md b/docs/resources/baremetal_server.md index 80a90bcbc6..e688e1a000 100644 --- a/docs/resources/baremetal_server.md +++ b/docs/resources/baremetal_server.md @@ -32,6 +32,8 @@ resource "scaleway_baremetal_server" "my_server" { ### With option +``` + ```terraform data "scaleway_iam_ssh_key" "my_ssh_key" { name = "main" @@ -75,6 +77,56 @@ resource "scaleway_baremetal_server" "base" { } ``` +### With cloud-init + +```terraform +data "scaleway_iam_ssh_key" "my_ssh_key" { + name = "main" +} + +data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-I220E-NVME" +} + +resource "scaleway_baremetal_server" "my_server_ci" { + zone = "fr-par-2" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + os = "d17d6872-0412-45d9-a198-af82c34d3c5c" + ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id] + + cloud_init = "cloud-init/userdata.yaml" +} +``` + +```terraform +data "scaleway_iam_ssh_key" "my_ssh_key" { + name = "main" +} + +data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-I220E-NVME" +} + +resource "scaleway_baremetal_server" "my_server_ci" { + zone = "fr-par-2" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + os = "d17d6872-0412-45d9-a198-af82c34d3c5c" + ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id] + + cloud_init = < /home/ubuntu/message.txt +EOF +} +``` + ### With private network ```terraform @@ -305,6 +357,8 @@ The following arguments are supported: - `ipam_ip_ids` - (Optional) List of IPAM IP IDs to assign to the server in the requested private network. - `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the server should be created. - `partitioning` (Optional) The partitioning schema in JSON format +- `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Only supported for OSes that have cloud-init enabled. +- `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Not all BareMetal offers and OS images support cloud-init — check the OS/offer metadata (for example `cloud_init_supported`) before use. - `protected` - (Optional) Set to true to activate server protection option. - `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the server is associated with. @@ -320,6 +374,7 @@ In addition to all arguments above, the following attributes are exported: - `offer_id` - The ID of the offer. - `offer_name` - The name of the offer. - `os_name` - The name of the os. +- `cloud_init` - The cloud-init user-data associated with the server. This value can be either a path to a file containing the user-data or the raw user-data content itself. Updating this field requires a server reboot for the changes to take effect. Only available for OS and offers that support cloud-init. - `private_network` - The private networks attached to the server. - `id` - The ID of the private network. - `mapping_id` - The ID of the Server-to-Private Network mapping. diff --git a/templates/resources/baremetal_server.md.tmpl b/templates/resources/baremetal_server.md.tmpl index 2032bcc451..fe65c805f4 100644 --- a/templates/resources/baremetal_server.md.tmpl +++ b/templates/resources/baremetal_server.md.tmpl @@ -33,6 +33,8 @@ resource "scaleway_baremetal_server" "my_server" { ### With option +``` + ```terraform data "scaleway_iam_ssh_key" "my_ssh_key" { name = "main" @@ -76,6 +78,56 @@ resource "scaleway_baremetal_server" "base" { } ``` +### With cloud-init + +```terraform +data "scaleway_iam_ssh_key" "my_ssh_key" { + name = "main" +} + +data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-I220E-NVME" +} + +resource "scaleway_baremetal_server" "my_server_ci" { + zone = "fr-par-2" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + os = "d17d6872-0412-45d9-a198-af82c34d3c5c" + ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id] + + cloud_init = "cloud-init/userdata.yaml" +} +``` + +```terraform +data "scaleway_iam_ssh_key" "my_ssh_key" { + name = "main" +} + +data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-I220E-NVME" +} + +resource "scaleway_baremetal_server" "my_server_ci" { + zone = "fr-par-2" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + os = "d17d6872-0412-45d9-a198-af82c34d3c5c" + ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id] + + cloud_init = < /home/ubuntu/message.txt +EOF +} +``` + ### With private network ```terraform @@ -306,6 +358,8 @@ The following arguments are supported: - `ipam_ip_ids` - (Optional) List of IPAM IP IDs to assign to the server in the requested private network. - `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the server should be created. - `partitioning` (Optional) The partitioning schema in JSON format +- `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Only supported for OSes that have cloud-init enabled. +- `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Not all BareMetal offers and OS images support cloud-init — check the OS/offer metadata (for example `cloud_init_supported`) before use. - `protected` - (Optional) Set to true to activate server protection option. - `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the server is associated with. @@ -321,6 +375,7 @@ In addition to all arguments above, the following attributes are exported: - `offer_id` - The ID of the offer. - `offer_name` - The name of the offer. - `os_name` - The name of the os. +- `cloud_init` - The cloud-init user-data associated with the server. This value can be either a path to a file containing the user-data or the raw user-data content itself. Updating this field requires a server reboot for the changes to take effect. Only available for OS and offers that support cloud-init. - `private_network` - The private networks attached to the server. - `id` - The ID of the private network. - `mapping_id` - The ID of the Server-to-Private Network mapping. From 6f4378c7af0e8bb4dfbbab4590088c9d7f8f423a Mon Sep 17 00:00:00 2001 From: Laure-di Date: Thu, 27 Nov 2025 15:03:20 +0100 Subject: [PATCH 3/4] fix(baremetal): manage security issue --- internal/services/baremetal/server.go | 46 ++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/internal/services/baremetal/server.go b/internal/services/baremetal/server.go index 8a9cbf4b40..4b564a9e3c 100644 --- a/internal/services/baremetal/server.go +++ b/internal/services/baremetal/server.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "os" + "path/filepath" + "strings" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -382,6 +384,7 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di if err != nil { return diag.FromErr(err) } + req.UserData = &userData } @@ -475,18 +478,51 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di return ResourceServerRead(ctx, d, m) } -func LoadUserDataBase64(cloudInit interface{}) ([]byte, error) { +func LoadUserDataBase64(cloudInit any) ([]byte, error) { value := cloudInit.(string) + var content []byte - if data, err := os.ReadFile(value); errors.Is(err, os.ErrNotExist) { - content = []byte(value) - } else if err == nil { + + // If value refers to an existing file, read it. Otherwise treat value as the content. + if fi, err := os.Stat(value); err == nil { + // Only allow regular files + if !fi.Mode().IsRegular() { + return nil, fmt.Errorf("cloud_init path is not a regular file: %s", value) + } + + // Resolve absolute path and ensure it is within the current working directory + absPath, err := filepath.Abs(value) + if err != nil { + return nil, err + } + + cwd, err := os.Getwd() + if err != nil { + return nil, err + } + + absPath = filepath.Clean(absPath) + cwd = filepath.Clean(cwd) + + if absPath != cwd && !strings.HasPrefix(absPath, cwd+string(os.PathSeparator)) { + return nil, fmt.Errorf("reading cloud_init from outside working directory is disallowed: %s", value) + } + + data, err := os.ReadFile(absPath) + if err != nil { + return nil, err + } + content = data + } else if errors.Is(err, os.ErrNotExist) { + content = []byte(value) } else { return nil, err } + encoded := base64.StdEncoding.EncodeToString(content) userData := []byte(encoded) + return userData, nil } @@ -732,10 +768,12 @@ func ResourceServerUpdate(ctx context.Context, d *schema.ResourceData, m any) di if d.HasChange("cloud_init") { cloudInit := d.Get("cloud_init").(string) + userData, err := LoadUserDataBase64(cloudInit) if err != nil { return diag.FromErr(err) } + req.UserData = &userData hasChanged = true } From ce213173151d56b565f3170501aaf437281388f6 Mon Sep 17 00:00:00 2001 From: Laure-di Date: Sun, 30 Nov 2025 13:28:29 +0100 Subject: [PATCH 4/4] test(baremetal): register cassettes --- docs/resources/baremetal_server.md | 6 +- internal/acctest/validate_cassettes_test.go | 29 +- internal/services/baremetal/server.go | 80 +- internal/services/baremetal/server_test.go | 173 + ...ud-init-not-compatible-offer.cassette.yaml | 550 ++ .../testdata/server-cloud-init.cassette.yaml | 6328 +++++++++++++++++ templates/resources/baremetal_server.md.tmpl | 6 +- 7 files changed, 7080 insertions(+), 92 deletions(-) create mode 100644 internal/services/baremetal/testdata/server-cloud-init-not-compatible-offer.cassette.yaml create mode 100644 internal/services/baremetal/testdata/server-cloud-init.cassette.yaml diff --git a/docs/resources/baremetal_server.md b/docs/resources/baremetal_server.md index e688e1a000..8c4595e7e0 100644 --- a/docs/resources/baremetal_server.md +++ b/docs/resources/baremetal_server.md @@ -32,8 +32,6 @@ resource "scaleway_baremetal_server" "my_server" { ### With option -``` - ```terraform data "scaleway_iam_ssh_key" "my_ssh_key" { name = "main" @@ -95,7 +93,7 @@ resource "scaleway_baremetal_server" "my_server_ci" { os = "d17d6872-0412-45d9-a198-af82c34d3c5c" ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id] - cloud_init = "cloud-init/userdata.yaml" + cloud_init = file("userdata.yaml") } ``` @@ -358,7 +356,6 @@ The following arguments are supported: - `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the server should be created. - `partitioning` (Optional) The partitioning schema in JSON format - `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Only supported for OSes that have cloud-init enabled. -- `cloud_init` - (Optional) Configuration data to pass to cloud-init such as a YAML cloud config or a user-data script. Accepts either a string containing the content or a path to a file (for example `file("cloud-init.yml")`). Max length: 127998 characters. Updates to `cloud_init` will update the server user-data via the API and do not trigger a reinstall; however, a reboot of the server is required for the OS to re-run cloud-init and apply the changes. Not all BareMetal offers and OS images support cloud-init — check the OS/offer metadata (for example `cloud_init_supported`) before use. - `protected` - (Optional) Set to true to activate server protection option. - `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the server is associated with. @@ -374,7 +371,6 @@ In addition to all arguments above, the following attributes are exported: - `offer_id` - The ID of the offer. - `offer_name` - The name of the offer. - `os_name` - The name of the os. -- `cloud_init` - The cloud-init user-data associated with the server. This value can be either a path to a file containing the user-data or the raw user-data content itself. Updating this field requires a server reboot for the changes to take effect. Only available for OS and offers that support cloud-init. - `private_network` - The private networks attached to the server. - `id` - The ID of the private network. - `mapping_id` - The ID of the Server-to-Private Network mapping. diff --git a/internal/acctest/validate_cassettes_test.go b/internal/acctest/validate_cassettes_test.go index 979cd720e5..62fadc8f66 100644 --- a/internal/acctest/validate_cassettes_test.go +++ b/internal/acctest/validate_cassettes_test.go @@ -25,20 +25,21 @@ const servicesDir = "../services" func exceptionsCassettesCases() map[string]struct{} { return map[string]struct{}{ - "../services/mnq/testdata/sns-topic-basic.cassette.yaml": {}, - "../services/mnq/testdata/sns-topic-subscription-basic.cassette.yaml": {}, - "../services/mnq/testdata/sqs-already-activated.cassette.yaml": {}, - "../services/object/testdata/bucket-cors-empty-origin.cassette.yaml": {}, - "../services/object/testdata/bucket-destroy-force.cassette.yaml": {}, - "../services/rdb/testdata/data-source-privilege-basic.cassette.yaml": {}, - "../services/rdb/testdata/privilege-basic.cassette.yaml": {}, - "../services/object/testdata/object-bucket-destroy-force.cassette.yaml": {}, - "../services/secret/testdata/secret-protected.cassette.yaml": {}, - "../services/secret/testdata/secret-version-type.cassette.yaml": {}, - "../services/file/testdata/file-system-invalid-size-granularity-fails.cassette.yaml": {}, - "../services/file/testdata/file-system-size-too-small-fails.cassette.yaml": {}, - "../services/container/testdata/namespace-vpc-integration.cassette.yaml": {}, - "../services/function/testdata/function-namespace-vpc-integration.cassette.yaml": {}, + "../services/mnq/testdata/sns-topic-basic.cassette.yaml": {}, + "../services/mnq/testdata/sns-topic-subscription-basic.cassette.yaml": {}, + "../services/mnq/testdata/sqs-already-activated.cassette.yaml": {}, + "../services/object/testdata/bucket-cors-empty-origin.cassette.yaml": {}, + "../services/object/testdata/bucket-destroy-force.cassette.yaml": {}, + "../services/rdb/testdata/data-source-privilege-basic.cassette.yaml": {}, + "../services/rdb/testdata/privilege-basic.cassette.yaml": {}, + "../services/object/testdata/object-bucket-destroy-force.cassette.yaml": {}, + "../services/secret/testdata/secret-protected.cassette.yaml": {}, + "../services/secret/testdata/secret-version-type.cassette.yaml": {}, + "../services/file/testdata/file-system-invalid-size-granularity-fails.cassette.yaml": {}, + "../services/file/testdata/file-system-size-too-small-fails.cassette.yaml": {}, + "../services/container/testdata/namespace-vpc-integration.cassette.yaml": {}, + "../services/function/testdata/function-namespace-vpc-integration.cassette.yaml": {}, + "../services/baremetal/testdata/server-cloud-init-not-compatible-offer.cassette.yaml": {}, } } diff --git a/internal/services/baremetal/server.go b/internal/services/baremetal/server.go index 4b564a9e3c..55fabf3a16 100644 --- a/internal/services/baremetal/server.go +++ b/internal/services/baremetal/server.go @@ -2,13 +2,8 @@ package baremetal import ( "context" - "encoding/base64" "encoding/json" - "errors" "fmt" - "os" - "path/filepath" - "strings" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -380,12 +375,8 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di } if cloudInit, ok := d.GetOk("cloud_init"); ok { - userData, err := LoadUserDataBase64(cloudInit) - if err != nil { - return diag.FromErr(err) - } - - req.UserData = &userData + cloudInitStr := []byte(cloudInit.(string)) + req.UserData = &cloudInitStr } partitioningSchema := baremetal.Schema{} @@ -478,54 +469,6 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di return ResourceServerRead(ctx, d, m) } -func LoadUserDataBase64(cloudInit any) ([]byte, error) { - value := cloudInit.(string) - - var content []byte - - // If value refers to an existing file, read it. Otherwise treat value as the content. - if fi, err := os.Stat(value); err == nil { - // Only allow regular files - if !fi.Mode().IsRegular() { - return nil, fmt.Errorf("cloud_init path is not a regular file: %s", value) - } - - // Resolve absolute path and ensure it is within the current working directory - absPath, err := filepath.Abs(value) - if err != nil { - return nil, err - } - - cwd, err := os.Getwd() - if err != nil { - return nil, err - } - - absPath = filepath.Clean(absPath) - cwd = filepath.Clean(cwd) - - if absPath != cwd && !strings.HasPrefix(absPath, cwd+string(os.PathSeparator)) { - return nil, fmt.Errorf("reading cloud_init from outside working directory is disallowed: %s", value) - } - - data, err := os.ReadFile(absPath) - if err != nil { - return nil, err - } - - content = data - } else if errors.Is(err, os.ErrNotExist) { - content = []byte(value) - } else { - return nil, err - } - - encoded := base64.StdEncoding.EncodeToString(content) - userData := []byte(encoded) - - return userData, nil -} - func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { api, zonedID, err := NewAPIWithZoneAndID(m, d.Id()) if err != nil { @@ -583,7 +526,13 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m any) diag _ = d.Set("ipv4", flattenIPv4s(server.IPs)) _ = d.Set("ipv6", flattenIPv6s(server.IPs)) _ = d.Set("protected", server.Protected) - _ = d.Set("cloud_init", server.UserData) + + var cloudInit string + if server.UserData != nil { + cloudInit = string(*server.UserData) + } + + _ = d.Set("cloud_init", cloudInit) if server.Install != nil { _ = d.Set("os", zonal.NewIDString(server.Zone, os.ID)) @@ -767,14 +716,9 @@ func ResourceServerUpdate(ctx context.Context, d *schema.ResourceData, m any) di hasChanged := false if d.HasChange("cloud_init") { - cloudInit := d.Get("cloud_init").(string) - - userData, err := LoadUserDataBase64(cloudInit) - if err != nil { - return diag.FromErr(err) - } - - req.UserData = &userData + cloudInit, _ := d.Get("cloud_init").(string) + cloudInitStr := []byte(cloudInit) + req.UserData = &cloudInitStr hasChanged = true } diff --git a/internal/services/baremetal/server_test.go b/internal/services/baremetal/server_test.go index 17699c47a7..e7274421ee 100644 --- a/internal/services/baremetal/server_test.go +++ b/internal/services/baremetal/server_test.go @@ -116,6 +116,179 @@ func TestAccServer_Basic(t *testing.T) { }) } +func TestAccServer_CloudInit(t *testing.T) { + tt := acctest.NewTestTools(t) + defer tt.Cleanup() + + if !IsOfferAvailable(OfferName, scw.Zone(Zone), tt) { + t.Skip("Offer is out of stock") + } + + SSHKeyName := "TestAccServer_CloudInit" + name := "TestAccServer_CloudInit" + + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: tt.ProviderFactories, + CheckDestroy: baremetalchecks.CheckServerDestroy(tt), + + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` + variable "cloud_init" { + type = string + default = <