Skip to content

Commit

Permalink
feat(rdb): instance resource
Browse files Browse the repository at this point in the history
  • Loading branch information
kindermoumoute committed Nov 21, 2019
1 parent 28e6b10 commit f5da9fc
Show file tree
Hide file tree
Showing 4 changed files with 373 additions and 0 deletions.
37 changes: 37 additions & 0 deletions scaleway/helpers_rdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package scaleway

import (
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/rdb/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

const (
RdbWaitForTimeout = 10 * time.Minute
)

// getRdbAPI returns a new RDB API
func getRdbAPI(m interface{}) *rdb.API {
meta := m.(*Meta)
return rdb.NewAPI(meta.scwClient)
}

// getRdbAPIWithRegion returns a new lb API and the region for a Create request
func getRdbAPIWithRegion(d *schema.ResourceData, m interface{}) (*rdb.API, scw.Region, error) {
meta := m.(*Meta)
rdbApi := rdb.NewAPI(meta.scwClient)

region, err := getRegion(d, meta)
return rdbApi, region, err
}

// getRdbAPIWithRegionAndID returns an lb API with region and ID extracted from the state
func getRdbAPIWithRegionAndID(m interface{}, id string) (*rdb.API, scw.Region, string, error) {
meta := m.(*Meta)
rdbApi := rdb.NewAPI(meta.scwClient)

region, ID, err := parseRegionalID(id)
return rdbApi, region, ID, err
}
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ func Provider() terraform.ResourceProvider {
"scaleway_lb_beta": resourceScalewayLbBeta(),
"scaleway_lb_backend_beta": resourceScalewayLbBackendBeta(),
"scaleway_lb_frontend_beta": resourceScalewayLbFrontendBeta(),
"scaleway_rdb_instance_beta": resourceScalewayRdbInstanceBeta(),
"scaleway_object_bucket": resourceScalewayObjectBucket(),
"scaleway_user_data": resourceScalewayUserData(),
"scaleway_server": resourceScalewayServer(),
Expand Down
206 changes: 206 additions & 0 deletions scaleway/resource_rdb_instance_beta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package scaleway

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/rdb/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func resourceScalewayRdbInstanceBeta() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayRdbInstanceBetaCreate,
Read: resourceScalewayRdbInstanceBetaRead,
Update: resourceScalewayRdbInstanceBetaUpdate,
Delete: resourceScalewayRdbInstanceBetaDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Instance database's name",
},
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The type of instance node you want to create",
},
"engine": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Database's engine version id",
},
"is_ha_cluster": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
Description: "Enable or disable high availability for database instance",
},
"disable_backup": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Disable automated backup on your database instance",
},
"user_name": {
Type: schema.TypeString,
Required: true,
Description: "Identifier of the first user of your database",
},
"password": {
Type: schema.TypeString,
Required: true,
Description: "Password for the first user",
},
"tags": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "list of tags [\"tag1\", \"tag2\", ...] attached to a database instance",
},

// TODO: computed (endpoint_ip,endpoint_port,read_replicas,certificate,backup_schedule)

"region": regionSchema(),
"organization_id": organizationIDSchema(),
},
}
}

func resourceScalewayRdbInstanceBetaCreate(d *schema.ResourceData, m interface{}) error {
rdbAPI, region, err := getRdbAPIWithRegion(d, m)
if err != nil {
return err
}

createReq := &rdb.CreateInstanceRequest{
Region: region,
OrganizationID: d.Get("organization_id").(string),
Name: expandOrGenerateString(d.Get("name"), "instance"),
NodeType: d.Get("type").(string),
Engine: d.Get("engine").(string),
IsHaCluster: d.Get("is_ha_cluster").(bool),
DisableBackup: d.Get("disable_backup").(bool),
UserName: d.Get("user_name").(string),
Password: d.Get("password").(string),
Tags: expandStrings(d.Get("tags")),
}

res, err := rdbAPI.CreateInstance(createReq)
if err != nil {
return err
}

d.SetId(newRegionalId(region, res.ID))

_, err = rdbAPI.WaitForInstance(&rdb.WaitForInstanceRequest{
Region: region,
InstanceID: res.ID,
Timeout: BaremetalServerWaitForTimeout,
})
if err != nil {
return err
}

return resourceScalewayRdbInstanceBetaRead(d, m)
}

func resourceScalewayRdbInstanceBetaRead(d *schema.ResourceData, m interface{}) error {
rdbAPI, region, ID, err := getRdbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

res, err := rdbAPI.GetInstance(&rdb.GetInstanceRequest{
Region: region,
InstanceID: ID,
})

if err != nil {
if is404Error(err) {
d.SetId("")
return nil
}
return err
}

d.Set("name", res.Name)
d.Set("type", res.NodeType)
d.Set("engine", res.Engine)
d.Set("is_ha_cluster", res.IsHaCluster)
d.Set("disable_backup", res.BackupSchedule.Disabled)
d.Set("user_name", d.Get("user_name").(string)) // user name and
d.Set("password", d.Get("password").(string)) // password are immutable
d.Set("tags", res.Tags)
d.Set("region", string(region))
d.Set("organization_id", res.OrganizationID)

return nil
}

func resourceScalewayRdbInstanceBetaUpdate(d *schema.ResourceData, m interface{}) error {
rdbAPI, region, ID, err := getRdbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

req := &rdb.UpdateInstanceRequest{
Region: region,
InstanceID: ID,
}

if d.HasChange("name") {
req.Name = scw.StringPtr(d.Get("name").(string))
}
if d.HasChange("disable_backup") {
req.IsBackupScheduleDisabled = scw.BoolPtr(d.Get("disable_backup").(bool))
}

//if d.HasChange("tags") {
req.Tags = scw.StringsPtr(StringSliceFromState(d.Get("tags").([]interface{}))) // due to a bug in the API Tags must always be sent for now
//}

// TODO: handle engine upgrade
_, err = rdbAPI.UpdateInstance(req)
if err != nil {
return err
}

return resourceScalewayRdbInstanceBetaRead(d, m)
}

func resourceScalewayRdbInstanceBetaDelete(d *schema.ResourceData, m interface{}) error {
rdbAPI, region, ID, err := getRdbAPIWithRegionAndID(m, d.Id())
if err != nil {
return err
}

_, err = rdbAPI.DeleteInstance(&rdb.DeleteInstanceRequest{
Region: region,
InstanceID: ID,
})

if err != nil && !is404Error(err) {
return err
}

_, err = rdbAPI.WaitForInstance(&rdb.WaitForInstanceRequest{
InstanceID: ID,
Region: region,
Timeout: LbWaitForTimeout,
})

if err != nil && !is404Error(err) {
return err
}

return nil
}
129 changes: 129 additions & 0 deletions scaleway/resource_rdb_instance_beta_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package scaleway

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
"github.com/scaleway/scaleway-sdk-go/api/rdb/v1"
)

func TestAccScalewayRdbInstanceBeta(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayRdbInstanceBetaDestroy,
Steps: []resource.TestStep{
{
Config: `
resource scaleway_rdb_instance_beta main {
name = "test-rdb"
type = "db-dev-s"
engine = "PostgreSQL-11"
is_ha_cluster = true
disable_backup = true
user_name = "my_initial_user"
password = "thiZ_is_v&ry_s3cret"
tags = [ "terraform-test", "scaleway_rdb_instance_beta", "minimal" ]
}
`,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayRdbBetaExists("scaleway_rdb_instance_beta.main"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "name", "test-rdb"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "type", "db-dev-s"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "engine", "PostgreSQL-11"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "is_ha_cluster", "true"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "disable_backup", "true"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "user_name", "my_initial_user"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "password", "thiZ_is_v&ry_s3cret"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.0", "terraform-test"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.1", "scaleway_rdb_instance_beta"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.2", "minimal"),
),
},
{
Config: `
resource scaleway_rdb_instance_beta main {
name = "test-rdb"
type = "db-dev-s"
engine = "PostgreSQL-11"
is_ha_cluster = true
disable_backup = false
user_name = "my_initial_user"
password = "thiZ_is_v&ry_s3cret"
tags = [ "terraform-test", "scaleway_rdb_instance_beta", "minimal" ]
}
`,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayRdbBetaExists("scaleway_rdb_instance_beta.main"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "name", "test-rdb"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "type", "db-dev-s"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "engine", "PostgreSQL-11"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "is_ha_cluster", "true"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "disable_backup", "false"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "user_name", "my_initial_user"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "password", "thiZ_is_v&ry_s3cret"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.0", "terraform-test"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.1", "scaleway_rdb_instance_beta"),
resource.TestCheckResourceAttr("scaleway_rdb_instance_beta.main", "tags.2", "minimal"),
),
},
},
})
}

func testAccCheckScalewayRdbBetaExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("resource not found: %s", n)
}

rdbAPI, region, ID, err := getRdbAPIWithRegionAndID(testAccProvider.Meta(), rs.Primary.ID)
if err != nil {
return err
}

_, err = rdbAPI.GetInstance(&rdb.GetInstanceRequest{
InstanceID: ID,
Region: region,
})

if err != nil {
return err
}

return nil
}
}

func testAccCheckScalewayRdbInstanceBetaDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "scaleway_rdb_instance_beta" {
continue
}

rdbAPI, region, ID, err := getRdbAPIWithRegionAndID(testAccProvider.Meta(), rs.Primary.ID)
if err != nil {
return err
}

_, err = rdbAPI.GetInstance(&rdb.GetInstanceRequest{
InstanceID: ID,
Region: region,
})

// If no error resource still exist
if err == nil {
return fmt.Errorf("Instance (%s) still exists", rs.Primary.ID)
}

// Unexpected api error we return it
if !is404Error(err) {
return err
}
}

return nil
}

0 comments on commit f5da9fc

Please sign in to comment.