Skip to content

Commit

Permalink
add scaleway_user_data resource, update scaleway_server
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolai86 committed Apr 7, 2018
1 parent f67919a commit 695ee42
Show file tree
Hide file tree
Showing 9 changed files with 458 additions and 0 deletions.
28 changes: 28 additions & 0 deletions scaleway/import_user_data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package scaleway

import (
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccScalewayUserData_importBasic(t *testing.T) {
resourceName := "scaleway_user_data.base"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayUserDataDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckScalewayUserDataConfig,
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Provider() terraform.ResourceProvider {
},

ResourcesMap: map[string]*schema.Resource{
"scaleway_user_data": resourceScalewayUserData(),
"scaleway_server": resourceScalewayServer(),
"scaleway_token": resourceScalewayToken(),
"scaleway_ssh_key": resourceScalewaySSHKey(),
Expand Down
91 changes: 91 additions & 0 deletions scaleway/resource_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scaleway

import (
"fmt"
"hash/fnv"
"log"

"github.com/hashicorp/terraform/helper/schema"
Expand All @@ -10,6 +11,8 @@ import (

var commercialServerTypes []string

var sshHostFingerprints = "ssh-host-fingerprints"

func resourceScalewayServer() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayServerCreate,
Expand Down Expand Up @@ -57,6 +60,29 @@ func resourceScalewayServer() *schema.Resource {
Optional: true,
Description: "The security group the server is attached to",
},
"user_data": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
},
"value": {
Type: schema.TypeString,
Required: true,
},
},
},
Set: func(val interface{}) int {
h := fnv.New32a()
userData := val.(map[string]interface{})
h.Write([]byte(userData["key"].(string)))
return int(h.Sum32())
},
Description: "User Data attached to the server on creation",
},
"volume": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -201,6 +227,17 @@ func resourceScalewayServerCreate(d *schema.ResourceData, m interface{}) error {
return err
}

if val, ok := d.GetOk("user_data"); ok {
s := val.(*schema.Set)
for _, v := range s.List() {
data := v.(map[string]interface{})
err := scaleway.PatchUserdata(server.Identifier, data["key"].(string), []byte(data["value"].(string)), false)
if err != nil {
return err
}
}
}

d.SetId(server.Identifier)
if d.Get("state").(string) != "stopped" {
task, err := scaleway.PostServerAction(server.Identifier, "poweron")
Expand Down Expand Up @@ -256,6 +293,26 @@ func resourceScalewayServerRead(d *schema.ResourceData, m interface{}) error {
d.Set("state_detail", server.StateDetail)
d.Set("tags", server.Tags)

userDatas := []map[string]interface{}{}
keys, err := scaleway.GetUserdatas(d.Id(), false)
if err != nil {
return err
}
for _, key := range keys.UserData {
if key == sshHostFingerprints {
continue
}
data, err := scaleway.GetUserdata(d.Id(), key, false)
if err != nil {
return err
}
userDatas = append(userDatas, map[string]interface{}{
"key": key,
"value": data.String(),
})
}
d.Set("user_data", userDatas)

d.SetConnInfo(map[string]string{
"type": "ssh",
"host": server.PublicAddress.IP,
Expand Down Expand Up @@ -304,6 +361,40 @@ func resourceScalewayServerUpdate(d *schema.ResourceData, m interface{}) error {
return fmt.Errorf("Failed patching scaleway server: %q", err)
}

if d.HasChange("user_data") {
remote, err := scaleway.GetUserdatas(d.Id(), false)
if err != nil {
return err
}

toDelete := []string{}
local := d.Get("user_data").(*schema.Set)
for _, key := range remote.UserData {
exists := false
for _, v := range local.List() {
exists = exists || v.(map[string]interface{})["key"] == key
}
if !exists {
toDelete = append(toDelete, key)
}
}
for _, key := range toDelete {
if err := scaleway.DeleteUserdata(d.Id(), key, false); err != nil {
return err
}
}

for _, v := range local.List() {
if err := scaleway.PatchUserdata(
d.Id(),
v.(map[string]interface{})["key"].(string),
[]byte(v.(map[string]interface{})["value"].(string)),
false); err != nil {
return err
}
}
}

if d.HasChange("public_ip") {
ips, err := scaleway.GetIPS()
if err != nil {
Expand Down
76 changes: 76 additions & 0 deletions scaleway/resource_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scaleway
import (
"fmt"
"log"
"strings"
"testing"

"github.com/hashicorp/terraform/helper/resource"
Expand Down Expand Up @@ -159,6 +160,47 @@ func TestAccScalewayServer_SecurityGroup(t *testing.T) {
})
}

func TestAccScalewayServer_UserData(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayServerDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckScalewayServerConfig_UserDatas,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayServerExists("scaleway_server.base"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.#", "2"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.527074092.key", "app"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.527074092.value", "lb"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.key", "roles"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.value", "ingress,egress"),
),
},
resource.TestStep{
Config: testAccCheckScalewayServerConfig_UserData,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayServerExists("scaleway_server.base"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.#", "1"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.key", "roles"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.value", "ingress,egress"),
),
},
resource.TestStep{
Config: strings.Replace(testAccCheckScalewayServerConfig_UserDatas, "ingress,egress", "ingress", -1),
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayServerExists("scaleway_server.base"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.#", "2"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.527074092.key", "app"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.527074092.value", "lb"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.key", "roles"),
resource.TestCheckResourceAttr("scaleway_server.base", "user_data.2562481374.value", "ingress"),
),
},
},
})
}

func testAccCheckScalewayServerDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*Client).scaleway

Expand Down Expand Up @@ -311,6 +353,40 @@ resource "scaleway_server" "base" {
tags = [ "terraform-test" ]
}`, armImageIdentifier)

var testAccCheckScalewayServerConfig_UserData = fmt.Sprintf(`
resource "scaleway_server" "base" {
name = "test"
# ubuntu 14.04
image = "%s"
type = "C1"
tags = [ "terraform-test" ]
state = "stopped"
user_data {
key = "roles"
value = "ingress,egress"
}
}`, armImageIdentifier)

var testAccCheckScalewayServerConfig_UserDatas = fmt.Sprintf(`
resource "scaleway_server" "base" {
name = "test"
# ubuntu 14.04
image = "%s"
type = "C1"
tags = [ "terraform-test" ]
state = "stopped"
user_data {
key = "roles"
value = "ingress,egress"
}
user_data {
key = "app"
value = "lb"
}
}`, armImageIdentifier)

var testAccCheckScalewayServerConfig_IPAttachment = fmt.Sprintf(`
resource "scaleway_ip" "base" {}
Expand Down
120 changes: 120 additions & 0 deletions scaleway/resource_user_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package scaleway

import (
"fmt"
"strings"

"github.com/hashicorp/terraform/helper/schema"
api "github.com/nicolai86/scaleway-sdk"
)

func resourceScalewayUserData() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayUserDataCreate,
Read: resourceScalewayUserDataRead,
Update: resourceScalewayUserDataUpdate,
Delete: resourceScalewayUserDataDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"server": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The server the meta data is associated with",
},
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The key of the user data to manage",
},
"value": {
Type: schema.TypeString,
Required: true,
Description: "The value of the user",
},
},
}
}

func resourceScalewayUserDataCreate(d *schema.ResourceData, m interface{}) error {
scaleway := m.(*Client).scaleway

mu.Lock()
if err := scaleway.PatchUserdata(
d.Get("server").(string),
d.Get("key").(string),
[]byte(d.Get("value").(string)),
false); err != nil {
return err
}
mu.Unlock()

d.SetId(fmt.Sprintf("userdata-%s-%s", d.Get("server").(string), d.Get("key").(string)))
return resourceScalewayUserDataRead(d, m)
}

func resourceScalewayUserDataRead(d *schema.ResourceData, m interface{}) error {
scaleway := m.(*Client).scaleway

if d.Get("server").(string) == "" {
// import case
parts := strings.Split(d.Id(), "-")
d.Set("key", parts[len(parts)-1])
d.Set("server", strings.Join(parts[1:len(parts)-1], "-"))
}
userdata, err := scaleway.GetUserdata(
d.Get("server").(string),
d.Get("key").(string),
false,
)

if err != nil {
if serr, ok := err.(api.APIError); ok {
if serr.StatusCode == 404 {
d.SetId("")
return nil
}
}
return err
}

d.Set("value", userdata.String())
return nil
}

func resourceScalewayUserDataUpdate(d *schema.ResourceData, m interface{}) error {
scaleway := m.(*Client).scaleway

mu.Lock()
if err := scaleway.PatchUserdata(
d.Get("server").(string),
d.Get("key").(string),
[]byte(d.Get("value").(string)),
false); err != nil {
return err
}
mu.Unlock()

return resourceScalewayUserDataRead(d, m)
}

func resourceScalewayUserDataDelete(d *schema.ResourceData, m interface{}) error {
scaleway := m.(*Client).scaleway

mu.Lock()
defer mu.Unlock()

err := scaleway.DeleteUserdata(
d.Get("server").(string),
d.Get("key").(string),
false)
if err != nil {
return err
}
d.SetId("")
return nil
}
Loading

0 comments on commit 695ee42

Please sign in to comment.