Skip to content
Merged
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
28 changes: 13 additions & 15 deletions docs/resources/instance_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ resource "scaleway_instance_snapshot" "server_snapshot" {
resource "scaleway_instance_image" "image" {
name = "image_with_extra_volumes"
root_volume_id = scaleway_instance_snapshot.server_snapshot.id
additional_volumes = [
additional_volume_ids = [
scaleway_instance_snapshot.volume_snapshot.id
]
}
Expand All @@ -83,9 +83,6 @@ The following arguments are supported:
- `name` - (Optional) The name of the image. If not provided it will be randomly generated.
- `architecture` - (Optional, default `x86_64`) The architecture the image is compatible with. Possible values are: `x86_64` or `arm`.
- `additional_volume_ids` - (Optional) List of IDs of the snapshots of the additional volumes to be attached to the image.

-> **Important:** For now it is only possible to have 1 additional_volume.

- `tags` - (Optional) A list of tags to apply to the image.
- `public` - (Optional) Set to `true` if the image is public.
- `zone` - (Defaults to provider `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the image should be created.
Expand All @@ -104,26 +101,27 @@ In addition to all arguments above, the following attributes are exported:
- `from_server_id` - ID of the server the image is based on (in case it is a backup).
- `state` - State of the image. Possible values are: `available`, `creating` or `error`.
- `organization_id` - The organization ID the image is associated with.
- `root_volume` - The description of the root volume attached to the image.

-> The `root_volume` block contains :
- `id` - The ID of the volume.
- `name` - The name of the volume.
- `size` - The size of the volume.
- `volume_type` - The type of volume, possible values are `l_ssd` and `sbs_snapshot`.

- `additional_volumes` - The description of the extra volumes attached to the image.

-> The `additional_volumes` block contains :
- `id` - The ID of the volume.
- `name` - The name of the volume.
- `export_uri` - The export URI of the volume.
- `size` - The size of the volume.
- `volume_type` - The type of volume, possible values are `l_ssd` and `b_ssd`.
- `creation_date` - Date of the volume creation.
- `modification_date` - Date of volume latest update.
- `organization` - The organization ID the volume is associated with.
- `project` - ID of the project the volume is associated with
- `volume_type` - The type of volume, possible values are `l_ssd` and `sbs_snapshot`.
- `tags` - List of tags associated with the volume.
- `state` - State of the volume.
- `zone` - The [zone](../guides/regions_and_zones.md#zones) in which the volume is.
- `server` - Description of the server containing the volume (in case the image is a backup from a server).

-> The `server` block contains :
- `id` - ID of the server containing the volume.
- `name` - Name of the server containing the volume.
-> The `server` block contains :
- `id` - ID of the server containing the volume.
- `name` - Name of the server containing the volume.

## Import

Expand Down
48 changes: 21 additions & 27 deletions internal/services/instance/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ func ResourceImage() *schema.Resource {
"additional_volume_ids": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
Expand Down Expand Up @@ -101,7 +100,7 @@ func ResourceImage() *schema.Resource {
Computed: true,
Description: "The state of the image [ available | creating | error ]",
},
"additional_volumes": {
"root_volume": {
Type: schema.TypeList,
Computed: true,
Description: "Specs of the additional volumes attached to the image",
Expand All @@ -117,11 +116,6 @@ func ResourceImage() *schema.Resource {
Description: "Name of the additional volume",
Computed: true,
},
"export_uri": {
Type: schema.TypeString,
Description: "URI of the additional volume",
Computed: true,
},
"size": {
Type: schema.TypeInt,
Description: "Size of the additional volume",
Expand All @@ -132,24 +126,33 @@ func ResourceImage() *schema.Resource {
Description: "Type of the additional volume",
Computed: true,
},
"creation_date": {
},
},
},
"additional_volumes": {
Type: schema.TypeList,
Computed: true,
Description: "Specs of the additional volumes attached to the image",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Description: "Date and time of the creation of the additional volume (RFC3339)",
Description: "UUID of the additional volume",
Computed: true,
},
"modification_date": {
"name": {
Type: schema.TypeString,
Description: "Date and time of the modification of the additional volume (RFC3339)",
Description: "Name of the additional volume",
Computed: true,
},
"organization": {
Type: schema.TypeString,
Description: "Organization ID of the additional volume",
"size": {
Type: schema.TypeInt,
Description: "Size of the additional volume",
Computed: true,
},
"project": {
"volume_type": {
Type: schema.TypeString,
Description: "Project ID of the additional volume",
Description: "Type of the additional volume",
Computed: true,
},
"tags": {
Expand All @@ -160,19 +163,9 @@ func ResourceImage() *schema.Resource {
Type: schema.TypeString,
},
},
"state": {
Type: schema.TypeString,
Description: "The state of the additional volume",
Computed: true,
},
"zone": {
Type: schema.TypeString,
Description: "Zone ID of the additional volume",
Computed: true,
},
"server": {
Type: schema.TypeMap,
Description: "Server",
Description: "Server containing the volume (in case the image is a backup from a server)",
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -262,6 +255,7 @@ func ResourceInstanceImageRead(ctx context.Context, d *schema.ResourceData, m an
_ = d.Set("name", image.Image.Name)
_ = d.Set("root_volume_id", zonal.NewIDString(image.Image.Zone, image.Image.RootVolume.ID))
_ = d.Set("architecture", image.Image.Arch)
_ = d.Set("root_volume", flattenImageRootVolume(image.Image.RootVolume, zone))
_ = d.Set("additional_volumes", flattenImageExtraVolumes(image.Image.ExtraVolumes, zone))
_ = d.Set("tags", image.Image.Tags)
_ = d.Set("public", image.Image.Public)
Expand Down
107 changes: 59 additions & 48 deletions internal/services/instance/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,68 +130,70 @@ func TestAccImage_ExternalBlockVolume(t *testing.T) {
{
Config: `
resource "scaleway_block_volume" "main" {
size_in_gb = 50
size_in_gb = 20
iops = 5000
}

resource "scaleway_block_snapshot" "main" {
volume_id = scaleway_block_volume.main.id
}
`,
},
{
Config: `
resource "scaleway_block_volume" "main" {
size_in_gb = 50
iops = 5000
}

resource "scaleway_block_volume" "additional1" {
size_in_gb = 50
size_in_gb = 20
iops = 15000
}
resource "scaleway_block_volume" "additional2" {
size_in_gb = 40
iops = 5000
}

resource "scaleway_block_snapshot" "main" {
volume_id = scaleway_block_volume.main.id
}

resource "scaleway_block_snapshot" "additional1" {
volume_id = scaleway_block_volume.additional1.id
}
resource "scaleway_block_snapshot" "additional2" {
volume_id = scaleway_block_volume.additional2.id
}

resource "scaleway_instance_image" "main" {
name = "tf-test-image-external-block-volume"
root_volume_id = scaleway_block_snapshot.main.id
additional_volume_ids = [scaleway_block_snapshot.additional1.id]
additional_volume_ids = [
scaleway_block_snapshot.additional1.id,
scaleway_block_snapshot.additional2.id
]
}
`,
Check: resource.ComposeTestCheckFunc(
instancechecks.DoesImageExists(tt, "scaleway_instance_image.main"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "root_volume_id", "scaleway_block_snapshot.main", "id"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "architecture", "x86_64"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volume_ids.#", "1"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volume_ids.#", "2"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volume_ids.0", "scaleway_block_snapshot.additional1", "id"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volume_ids.1", "scaleway_block_snapshot.additional2", "id"),
),
},
{
Config: `
resource "scaleway_block_volume" "main" {
size_in_gb = 50
size_in_gb = 20
iops = 5000
}

resource "scaleway_block_volume" "additional1" {
size_in_gb = 50
size_in_gb = 20
iops = 15000
}
resource "scaleway_block_volume" "additional2" {
size_in_gb = 40
iops = 5000
}

resource "scaleway_block_snapshot" "main" {
volume_id = scaleway_block_volume.main.id
}

resource "scaleway_block_snapshot" "additional1" {
volume_id = scaleway_block_volume.additional1.id
}
resource "scaleway_block_snapshot" "additional2" {
volume_id = scaleway_block_volume.additional2.id
}

resource "scaleway_instance_image" "main" {
name = "tf-test-image-external-block-volume"
Expand Down Expand Up @@ -463,49 +465,40 @@ func TestAccImage_ServerWithLocalVolume(t *testing.T) {
volume_type = "l_ssd"
}
}
resource "scaleway_instance_snapshot" "local01" {
volume_id = scaleway_instance_server.server01.root_volume.0.volume_id
depends_on = [ scaleway_instance_server.server01 ]
}
`,
Check: resource.ComposeTestCheckFunc(
isServerPresent(tt, "scaleway_instance_server.server01"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local01"),
),
},
{
Config: `
resource "scaleway_instance_server" "server01" {
resource "scaleway_instance_server" "server02" {
image = "ubuntu_focal"
type = "DEV1-S"
root_volume {
size_in_gb = 15
size_in_gb = 10
volume_type = "l_ssd"
}
}
resource "scaleway_instance_server" "server02" {
resource "scaleway_instance_server" "server03" {
image = "ubuntu_focal"
type = "DEV1-S"
root_volume {
size_in_gb = 10
size_in_gb = 20
volume_type = "l_ssd"
}
}

resource "scaleway_instance_snapshot" "local01" {
volume_id = scaleway_instance_server.server01.root_volume.0.volume_id
depends_on = [ scaleway_instance_server.server01 ]
}
resource "scaleway_instance_snapshot" "local02" {
volume_id = scaleway_instance_server.server02.root_volume.0.volume_id
depends_on = [ scaleway_instance_server.server02 ]
}
resource "scaleway_instance_snapshot" "local03" {
volume_id = scaleway_instance_server.server03.root_volume.0.volume_id
}
`,
Check: resource.ComposeTestCheckFunc(
isServerPresent(tt, "scaleway_instance_server.server01"),
isServerPresent(tt, "scaleway_instance_server.server02"),
isServerPresent(tt, "scaleway_instance_server.server03"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local01"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local02"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local03"),
),
},
{
Expand All @@ -526,35 +519,53 @@ func TestAccImage_ServerWithLocalVolume(t *testing.T) {
volume_type = "l_ssd"
}
}
resource "scaleway_instance_server" "server03" {
image = "ubuntu_focal"
type = "DEV1-S"
root_volume {
size_in_gb = 20
volume_type = "l_ssd"
}
}

resource "scaleway_instance_snapshot" "local01" {
name = "snap01"
volume_id = scaleway_instance_server.server01.root_volume.0.volume_id
depends_on = [ scaleway_instance_server.server01 ]
}
resource "scaleway_instance_snapshot" "local02" {
name = "snap02"
volume_id = scaleway_instance_server.server02.root_volume.0.volume_id
depends_on = [ scaleway_instance_server.server02 ]
}
resource "scaleway_instance_snapshot" "local03" {
name = "snap03"
volume_id = scaleway_instance_server.server03.root_volume.0.volume_id
}

resource "scaleway_instance_image" "main" {
root_volume_id = scaleway_instance_snapshot.local01.id
additional_volume_ids = [ scaleway_instance_snapshot.local02.id ]
depends_on = [
scaleway_instance_snapshot.local01,
scaleway_instance_snapshot.local02,
additional_volume_ids = [
scaleway_instance_snapshot.local02.id,
scaleway_instance_snapshot.local03.id
]
}
`,
Check: resource.ComposeTestCheckFunc(
isServerPresent(tt, "scaleway_instance_server.server01"),
isServerPresent(tt, "scaleway_instance_server.server02"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local01"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local02"),
isSnapshotPresent(tt, "scaleway_instance_snapshot.local03"),
instancechecks.DoesImageExists(tt, "scaleway_instance_image.main"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "root_volume_id", "scaleway_instance_snapshot.local01", "id"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "root_volume.0.id", "scaleway_instance_snapshot.local01", "id"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "root_volume.0.volume_type", "l_ssd"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "root_volume.0.size", "15000000000"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volume_ids.0", "scaleway_instance_snapshot.local02", "id"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volumes.0.id", "scaleway_instance_snapshot.local02", "id"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volumes.0.volume_type", "l_ssd"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volumes.0.size", "10000000000"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volume_ids.1", "scaleway_instance_snapshot.local03", "id"),
resource.TestCheckResourceAttrPair("scaleway_instance_image.main", "additional_volumes.1.id", "scaleway_instance_snapshot.local03", "id"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volumes.1.volume_type", "l_ssd"),
resource.TestCheckResourceAttr("scaleway_instance_image.main", "additional_volumes.1.size", "20000000000"),
),
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/services/instance/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func ResourceServer() *schema.Resource {
Type: schema.TypeMap,
Optional: true,
Computed: true,
Description: "The user data associated with the server", // TODO: document reserved keys (`cloud-init`)
Description: "The user data associated with the server",
Elem: &schema.Schema{
Type: schema.TypeString,
},
Expand Down
Loading
Loading