Skip to content
Open
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
51 changes: 51 additions & 0 deletions docs/resources/baremetal_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,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 = file("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 = <<EOF
#cloud-config
packages:
- htop
- curl

runcmd:
- echo "Hello from raw cloud-init!" > /home/ubuntu/message.txt
EOF
}
```

### With private network

```terraform
Expand Down Expand Up @@ -305,6 +355,7 @@ 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.
- `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.

Expand Down
29 changes: 15 additions & 14 deletions internal/acctest/validate_cassettes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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": {},
}
}

Expand Down
26 changes: 26 additions & 0 deletions internal/services/baremetal/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,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(),
Expand Down Expand Up @@ -367,6 +374,11 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di
Protected: d.Get("protected").(bool),
}

if cloudInit, ok := d.GetOk("cloud_init"); ok {
cloudInitStr := []byte(cloudInit.(string))
req.UserData = &cloudInitStr
}

partitioningSchema := baremetal.Schema{}

if file, ok := d.GetOk("partitioning"); ok || !d.Get("install_config_afterward").(bool) {
Expand Down Expand Up @@ -515,6 +527,13 @@ func ResourceServerRead(ctx context.Context, d *schema.ResourceData, m any) diag
_ = d.Set("ipv6", flattenIPv6s(server.IPs))
_ = d.Set("protected", server.Protected)

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))
_ = d.Set("os_name", os.Name)
Expand Down Expand Up @@ -696,6 +715,13 @@ func ResourceServerUpdate(ctx context.Context, d *schema.ResourceData, m any) di

hasChanged := false

if d.HasChange("cloud_init") {
cloudInit, _ := d.Get("cloud_init").(string)
cloudInitStr := []byte(cloudInit)
req.UserData = &cloudInitStr
hasChanged = true
}

if d.HasChange("name") {
req.Name = types.ExpandUpdatedStringPtr(d.Get("name"))
hasChanged = true
Expand Down
173 changes: 173 additions & 0 deletions internal/services/baremetal/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <<EOF
#cloud-config
apt_update: true
apt_upgrade: true
EOF
}

data "scaleway_baremetal_os" "my_os" {
zone = "%s"
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 = "%s"
description = "test a description"
offer = "%s"
os = data.scaleway_baremetal_os.my_os.os_id

cloud_init = var.cloud_init

tags = ["terraform-test", "scaleway_baremetal_server", "cloudinit"]
ssh_key_ids = [scaleway_iam_ssh_key.main.id]
}
`, Zone, SSHKeyName, SSHKeyBaremetal, name, Zone, OfferName),

Check: resource.ComposeTestCheckFunc(
testAccCheckBaremetalServerExists(tt, "scaleway_baremetal_server.base"),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "name", name),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "offer_name", OfferName),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "cloud_init", "#cloud-config\napt_update: true\napt_upgrade: true\n"),
),
},

{
// Update cloud-init + reinstall
Config: fmt.Sprintf(`
variable "cloud_init" {
type = string
default = <<EOF
#cloud-config
apt_update: true
apt_upgrade: true

packages:
- curl
EOF
}

data "scaleway_baremetal_os" "my_os" {
zone = "%s"
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 = "%s"
description = "test a description"
offer = "%s"
os = data.scaleway_baremetal_os.my_os.os_id

cloud_init = var.cloud_init

tags = ["terraform-test", "scaleway_baremetal_server", "cloudinit", "edited"]
ssh_key_ids = [scaleway_iam_ssh_key.main.id]
}
`, Zone, SSHKeyName, SSHKeyBaremetal, name, Zone, OfferName),

Check: resource.ComposeTestCheckFunc(
testAccCheckBaremetalServerExists(tt, "scaleway_baremetal_server.base"),
resource.TestCheckResourceAttr(
"scaleway_baremetal_server.base",
"cloud_init",
"#cloud-config\napt_update: true\napt_upgrade: true\n\npackages:\n - curl\n",
),
resource.TestCheckResourceAttr("scaleway_baremetal_server.base", "tags.#", "4"),
),
},
},
})
}

func TestAccServer_CloudInitNotCompatibleOffer(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_CloudInitIncompatibleOffer"
name := "TestAccServer_CloudInitIncompatibleOffer"
OfferNameNotCompatible := "EM-L110X-SATA"

resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: tt.ProviderFactories,
CheckDestroy: baremetalchecks.CheckServerDestroy(tt),

Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
variable "cloud_init" {
type = string
default = <<EOF
#cloud-config
apt_update: true
apt_upgrade: true
EOF
}

data "scaleway_baremetal_os" "my_os" {
zone = "%s"
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 = "%s"
description = "test a description"
offer = "%s"
os = data.scaleway_baremetal_os.my_os.os_id

cloud_init = var.cloud_init

tags = ["terraform-test", "scaleway_baremetal_server", "cloudinit"]
ssh_key_ids = [scaleway_iam_ssh_key.main.id]
}
`, Zone, SSHKeyName, SSHKeyBaremetal, name, Zone, OfferNameNotCompatible),

ExpectError: regexp.MustCompile("cloud-init is not supported on this offer"),
},
},
})
}

func TestAccServer_RequiredInstallConfig(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
Expand Down

Large diffs are not rendered by default.

6,328 changes: 6,328 additions & 0 deletions internal/services/baremetal/testdata/server-cloud-init.cassette.yaml

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions templates/resources/baremetal_server.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,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 = file("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"
Copy link
Member

Choose a reason for hiding this comment

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

Please use a data source and no hard coded values

ssh_key_ids = [data.scaleway_iam_ssh_key.my_ssh_key.id]

cloud_init = <<EOF
#cloud-config
packages:
- htop
- curl

runcmd:
- echo "Hello from raw cloud-init!" > /home/ubuntu/message.txt
EOF
}
```

### With private network

```terraform
Expand Down Expand Up @@ -306,6 +356,7 @@ 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.
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a way to see if cloud init is supported or not?

- `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.

Expand Down
Loading