provider/scaleway server volume property (#9695)

* provider/scaleway: extract volume validation helpers

* provider/scaleway: add server volume property

fixes #9499

* provider/scaleway: update `scaleway_server` docu

* provider/scaleway: fix volume handling

this actually broken when merging the latest SDK update :(

* provider/scaleway: fix volume attachment

* provider/scaleway: fix volume expectation
This commit is contained in:
Raphael Randschau 2016-10-29 13:07:35 +02:00 committed by Paul Stack
parent 18b3736ba4
commit 98d84680b7
7 changed files with 140 additions and 24 deletions

View File

@ -18,6 +18,22 @@ func String(val string) *string {
return &val
}
func validateVolumeType(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if value != "l_ssd" {
errors = append(errors, fmt.Errorf("%q must be l_ssd", k))
}
return
}
func validateVolumeSize(v interface{}, k string) (ws []string, errors []error) {
value := v.(int)
if value < 1 || value > 150 {
errors = append(errors, fmt.Errorf("%q be more than 1 and less than 150", k))
}
return
}
// deleteRunningServer terminates the server and waits until it is removed.
func deleteRunningServer(scaleway *api.ScalewayAPI, server *api.ScalewayServer) error {
err := scaleway.PostServerAction(server.Identifier, "terminate")

View File

@ -57,6 +57,29 @@ func resourceScalewayServer() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"volume": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size_in_gb": {
Type: schema.TypeInt,
Required: true,
ValidateFunc: validateVolumeSize,
},
"type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validateVolumeType,
},
"volume_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
},
},
"private_ip": &schema.Schema{
Type: schema.TypeString,
Computed: true,
@ -97,6 +120,28 @@ func resourceScalewayServerCreate(d *schema.ResourceData, m interface{}) error {
server.Bootscript = String(bootscript.(string))
}
if vs, ok := d.GetOk("volume"); ok {
server.Volumes = make(map[string]string)
volumes := vs.([]interface{})
for i, v := range volumes {
volume := v.(map[string]interface{})
volumeID, err := scaleway.PostVolume(api.ScalewayVolumeDefinition{
Size: uint64(volume["size_in_gb"].(int)) * gb,
Type: volume["type"].(string),
Name: fmt.Sprintf("%s-%d", server.Name, volume["size_in_gb"].(int)),
})
if err != nil {
return err
}
volume["volume_id"] = volumeID
volumes[i] = volume
server.Volumes[fmt.Sprintf("%d", i+1)] = volumeID
}
d.Set("volume", volumes)
}
if raw, ok := d.GetOk("tags"); ok {
for _, tag := range raw.([]interface{}) {
server.Tags = append(server.Tags, tag.(string))

View File

@ -31,6 +31,39 @@ func TestAccScalewayServer_Basic(t *testing.T) {
})
}
func TestAccScalewayServer_Volumes(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayServerDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckScalewayServerVolumeConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayServerExists("scaleway_server.base"),
testAccCheckScalewayServerAttributes("scaleway_server.base"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "type", "C1"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "volume.#", "2"),
resource.TestCheckResourceAttrSet(
"scaleway_server.base", "volume.0.volume_id"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "volume.0.type", "l_ssd"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "volume.0.size_in_gb", "20"),
resource.TestCheckResourceAttrSet(
"scaleway_server.base", "volume.1.volume_id"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "volume.1.type", "l_ssd"),
resource.TestCheckResourceAttr(
"scaleway_server.base", "volume.1.size_in_gb", "30"),
),
},
},
})
}
func TestAccScalewayServer_SecurityGroup(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -161,6 +194,25 @@ resource "scaleway_server" "base" {
tags = [ "terraform-test" ]
}`, armImageIdentifier)
var testAccCheckScalewayServerVolumeConfig = fmt.Sprintf(`
resource "scaleway_server" "base" {
name = "test"
# ubuntu 14.04
image = "%s"
type = "C1"
tags = [ "terraform-test" ]
volume {
size_in_gb = 20
type = "l_ssd"
}
volume {
size_in_gb = 30
type = "l_ssd"
}
}`, armImageIdentifier)
var testAccCheckScalewayServerConfig_SecurityGroup = fmt.Sprintf(`
resource "scaleway_security_group" "blue" {
name = "blue"

View File

@ -26,26 +26,14 @@ func resourceScalewayVolume() *schema.Resource {
Required: true,
},
"size_in_gb": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(int)
if value < 1 || value > 150 {
errors = append(errors, fmt.Errorf("%q be more than 1 and less than 150", k))
}
return
},
Type: schema.TypeInt,
Required: true,
ValidateFunc: validateVolumeSize,
},
"type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if value != "l_ssd" {
errors = append(errors, fmt.Errorf("%q must be l_ssd", k))
}
return
},
Type: schema.TypeString,
Required: true,
ValidateFunc: validateVolumeType,
},
"server": &schema.Schema{
Type: schema.TypeString,
@ -88,8 +76,8 @@ func resourceScalewayVolumeRead(d *schema.ResourceData, m interface{}) error {
return err
}
d.Set("name", volume.Name)
if size, ok := volume.Size.(uint64); ok {
d.Set("size_in_gb", size/gb)
if size, ok := volume.Size.(float64); ok {
d.Set("size_in_gb", uint64(size)/gb)
}
d.Set("type", volume.VolumeType)
d.Set("server", "")

View File

@ -69,7 +69,7 @@ func resourceScalewayVolumeAttachmentCreate(d *schema.ResourceData, m interface{
// the API request requires most volume attributes to be unset to succeed
for k, v := range volumes {
v.Size = 0
v.Size = nil
v.CreationDate = ""
v.Organization = ""
v.ModificationDate = ""
@ -174,7 +174,7 @@ func resourceScalewayVolumeAttachmentDelete(d *schema.ResourceData, m interface{
// the API request requires most volume attributes to be unset to succeed
for k, v := range volumes {
v.Size = 0
v.Size = nil
v.CreationDate = ""
v.Organization = ""
v.ModificationDate = ""

View File

@ -60,7 +60,7 @@ func testAccCheckScalewayVolumeAttributes(n string) resource.TestCheckFunc {
if volume.Name != "test" {
return fmt.Errorf("volume has wrong name: %q", volume.Name)
}
if volume.Size != 2000000000 {
if volume.Size != 2e+09 {
return fmt.Errorf("volume has wrong size: %d", volume.Size)
}
if volume.VolumeType != "l_ssd" {

View File

@ -17,7 +17,12 @@ For additional details please refer to [API documentation](https://developer.sca
resource "scaleway_server" "test" {
name = "test"
image = "5faef9cd-ea9b-4a63-9171-9e26bec03dbc"
type = "C1"
type = "VC1M"
volume {
size_in_gb = 20
type = "l_ssd"
}
}
```
@ -36,6 +41,16 @@ The following arguments are supported:
Field `name`, `type`, `tags`, `dynamic_ip_required`, `security_group` are editable.
## Volume
You can attach additional volumes to your instance, which will share the lifetime
of your `scaleway_server` resource.
The `volume` mapping supports the following:
* `type` - (Required) The type of volume. Can be `"l_ssd"`
* `size_in_gb` - (Required) The size of the volume in gigabytes.
## Attributes Reference
The following attributes are exported: