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

feat(lb): add lb beta resource #278

Merged
merged 7 commits into from
Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from 3 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
25 changes: 25 additions & 0 deletions scaleway/helpers_lb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package scaleway

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

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

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

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

region, ID, err := parseRegionalID(id)
return lbApi, region, ID, err
}
35 changes: 35 additions & 0 deletions scaleway/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package scaleway

import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"net"
"net/http"
"strings"
"testing"
Expand Down Expand Up @@ -192,3 +195,35 @@ func TestGetRandomName(t *testing.T) {
name := getRandomName("test")
assert.True(t, strings.HasPrefix(name, "tf-test-"))
}

func testCheckResourceAttrFunc(name string, key string, test func(string) error) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("resource not found: %s", name)
}
value, ok := rs.Primary.Attributes[key]
if !ok {
return fmt.Errorf("key not found: %s", key)
}
err := test(value)
if err != nil {
return fmt.Errorf("test for %s %s did not pass test: %w", name, key, err)
}
return nil
}
}

func testCheckResourceAttrUUID(name string, key string) resource.TestCheckFunc {
return resource.TestMatchResourceAttr(name, key, UUIDRegex)
}

func testCheckResourceAttrIPv4(name string, key string) resource.TestCheckFunc {
return testCheckResourceAttrFunc(name, key, func(value string) error {
ip := net.ParseIP(value)
if ip.To4() == nil {
return fmt.Errorf("%s is not a valid IPv4", value)
}
return nil
})
}
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func Provider() terraform.ResourceProvider {
"scaleway_instance_placement_group": resourceScalewayInstancePlacementGroup(),
"scaleway_k8s_cluster_beta": resourceScalewayK8SClusterBeta(),
"scaleway_k8s_pool_beta": resourceScalewayK8SPoolBeta(),
"scaleway_lb_beta": resourceScalewayLbBeta(),
"scaleway_object_bucket": resourceScalewayObjectBucket(),
"scaleway_user_data": resourceScalewayUserData(),
"scaleway_server": resourceScalewayServer(),
Expand Down
169 changes: 169 additions & 0 deletions scaleway/resource_lb_beta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package scaleway

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

func resourceScalewayLbBeta() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayLbBetaCreate,
Read: resourceScalewayLbBetaRead,
Update: resourceScalewayLbBetaUpdate,
Delete: resourceScalewayLbBetaDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Name of the lb",
},
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The type of load-balancer you want to create",
},
"tags": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "Array of tags to associate with the load-balancer",
},
"ip_id": {
Type: schema.TypeString,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Need a Description

},
"ip_address": {
Type: schema.TypeString,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Need a Description

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

func resourceScalewayLbBetaCreate(d *schema.ResourceData, m interface{}) error {
lbAPI, region, err := getLbAPIWithRegion(d, m)
if err != nil {
return err
}

name, ok := d.GetOk("name")
if !ok {
name = getRandomName("lb")
}
createReq := &lb.CreateLbRequest{
Region: region,
OrganizationID: d.Get("organization_id").(string),
Name: name.(string),
Type: d.Get("type").(string),
}
if raw, ok := d.GetOk("tags"); ok {
for _, tag := range raw.([]interface{}) {
createReq.Tags = append(createReq.Tags, tag.(string))
}
}
res, err := lbAPI.CreateLb(createReq)
if err != nil {
return err
}

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

_, err = lbAPI.WaitForLb(&lb.WaitForLbRequest{
Region: region,
LbID: res.ID,
Timeout: BaremetalServerWaitForTimeout,
})
if err != nil {
return err
}

return resourceScalewayLbBetaRead(d, m)
}

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

res, err := lbAPI.GetLb(&lb.GetLbRequest{
Region: region,
LbID: ID,
})

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

d.Set("name", res.Name)
d.Set("region", string(region))
d.Set("organization_id", res.OrganizationID)
d.Set("tags", res.Tags)
d.Set("type", res.Type)
d.Set("ip_id", res.IP[0].ID)
d.Set("ip_address", res.IP[0].IPAddress)

return nil
}

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

if d.HasChange("name") || d.HasChange("tags") {

req := &lb.UpdateLbRequest{
Region: region,
LbID: ID,
Name: d.Get("name").(string),
Tags: StringSliceFromState(d.Get("tags").([]interface{})),
}

_, err = lbAPI.UpdateLb(req)
if err != nil {
return err
}
}

return resourceScalewayLbBetaRead(d, m)
}

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

err = lbAPI.DeleteLb(&lb.DeleteLbRequest{
Region: region,
LbID: ID,
// This parameter will probably be breaking change when ip pre reservation will exist.
ReleaseIP: true,
})

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

if is404Error(err) {
return nil
}

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

import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/scaleway/scaleway-sdk-go/api/lb/v1"
"testing"
)

func TestAccScalewayLbBeta(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckScalewayLbBetaDestroy,
Steps: []resource.TestStep{
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "LB-S"
}
`,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayLbBetaExists("scaleway_lb_beta.lb01"),
resource.TestCheckResourceAttr("scaleway_lb_beta.lb01", "name", "test-lb"),
testCheckResourceAttrUUID("scaleway_lb_beta.lb01", "ip_id"),
testCheckResourceAttrIPv4("scaleway_lb_beta.lb01", "ip_address"),
),
},
{
Config: `
resource scaleway_lb_beta lb01 {
name = "test-lb"
type = "LB-S"
tags = ["tag1", "tag2"]
}
`,
Check: resource.ComposeTestCheckFunc(
testAccCheckScalewayLbBetaExists("scaleway_lb_beta.lb01"),
resource.TestCheckResourceAttr("scaleway_lb_beta.lb01", "name", "test-lb"),
resource.TestCheckResourceAttr("scaleway_lb_beta.lb01", "tags.0", "tag1"),
resource.TestCheckResourceAttr("scaleway_lb_beta.lb01", "tags.1", "tag2"),
testCheckResourceAttrUUID("scaleway_lb_beta.lb01", "ip_id"),
testCheckResourceAttrIPv4("scaleway_lb_beta.lb01", "ip_address"),
),
},
},
})
}

func testAccCheckScalewayLbBetaExists(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)
}

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

_, err = lbAPI.GetLb(&lb.GetLbRequest{
LbID: ID,
Region: region,
})

if err != nil {
return err
}

return nil
}
}

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

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

_, err = lbAPI.GetLb(&lb.GetLbRequest{
Region: region,
LbID: ID,
})

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

// Unexpected api error we return it
// We check for 403 because instance API return 403 for deleted IP
if !is404Error(err) {
return err
}
}

return nil
}
Loading