Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add scaleway_user_data resource #57

Merged
merged 1 commit into from
Apr 10, 2018
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: 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