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 backend beta resource #303

Merged
merged 11 commits into from
Oct 25, 2019
Merged
Show file tree
Hide file tree
Changes from 5 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
45 changes: 45 additions & 0 deletions scaleway/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,48 @@ func testAccGetResourceAttr(resourceName string, attrName string, dest *string)
return nil
}
}

func flattenDuration(duration *time.Duration) interface{} {
if duration != nil {
return duration.String()
}
return ""
}

func expandDuration(data interface{}) *time.Duration {
if data == nil || data == "" {
return nil
}
d, err := time.ParseDuration(data.(string))
if err != nil {
// We panic as this should never happend. Data from state should be validate using a validate func
panic(err)
}
return &d
}

func difSuppressFuncDuration(k, old, new string, d *schema.ResourceData) bool {
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
if old == new {
return true
}
d1, err1 := time.ParseDuration(old)
d2, err2 := time.ParseDuration(new)
if err1 != nil || err2 != nil {
return false
}
return d1 == d2
}

func validateDuration() schema.SchemaValidateFunc {
return func(i interface{}, s string) (strings []string, errors []error) {
str, isStr := i.(string)
if !isStr {
return nil, []error{fmt.Errorf("%v is not a string", i)}
}
_, err := time.ParseDuration(str)
if err != nil {
return nil, []error{fmt.Errorf("cannot parse duration for value %s", str)}
}
return nil, nil
}
}
50 changes: 50 additions & 0 deletions scaleway/helpers_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import (
"github.com/scaleway/scaleway-sdk-go/scw"
)

// getLbAPI returns a new lb API
func getLbAPI(m interface{}) *lb.API {
meta := m.(*Meta)
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
return lb.NewAPI(meta.scwClient)
}

// 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)
Expand All @@ -23,3 +29,47 @@ func getLbAPIWithRegionAndID(m interface{}, id string) (*lb.API, scw.Region, str
region, ID, err := parseRegionalID(id)
return lbApi, region, ID, err
}

func flattenLbBackendMarkdownAction(action lb.OnMarkedDownAction) interface{} {
if action == lb.OnMarkedDownActionOnMarkedDownActionNone {
return "none"
}
return action.String()
}

func expandLbBackendMarkdownAction(raw interface{}) lb.OnMarkedDownAction {
if raw == "none" {
return lb.OnMarkedDownActionOnMarkedDownActionNone
}
return lb.OnMarkedDownAction(raw.(string))
}

func flattenLbProtocol(protocol lb.Protocol) interface{} {
return protocol.String()
}

func expandLbProtocol(raw interface{}) lb.Protocol {
return lb.Protocol(raw.(string))
}

func flattenLbForwardPortAlgorithm(algo lb.ForwardPortAlgorithm) interface{} {
return algo.String()
}

func expandLbForwardPortAlgorithm(raw interface{}) lb.ForwardPortAlgorithm {
return lb.ForwardPortAlgorithm(raw.(string))
}

func flattenLbStickySessionsType(t lb.StickySessionsType) interface{} {
if t == lb.StickySessionsTypeNone {
return "none"
}
return t.String()
}

func expandLbStickySessionsType(raw interface{}) lb.StickySessionsType {
if raw == "none" {
return lb.StickySessionsTypeNone
}
return lb.StickySessionsType(raw.(string))
}
4 changes: 2 additions & 2 deletions scaleway/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package scaleway

import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"net"
"net/http"
"strings"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ func Provider() terraform.ResourceProvider {
"scaleway_k8s_cluster_beta": resourceScalewayK8SClusterBeta(),
"scaleway_k8s_pool_beta": resourceScalewayK8SPoolBeta(),
"scaleway_lb_beta": resourceScalewayLbBeta(),
"scaleway_lb_backend_beta": resourceScalewayLbBackendBeta(),
"scaleway_object_bucket": resourceScalewayObjectBucket(),
"scaleway_user_data": resourceScalewayUserData(),
"scaleway_server": resourceScalewayServer(),
Expand Down
262 changes: 262 additions & 0 deletions scaleway/resource_lb_backend_beta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package scaleway

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

func resourceScalewayLbBackendBeta() *schema.Resource {
return &schema.Resource{
Create: resourceScalewayLbBackendBetaCreate,
Read: resourceScalewayLbBackendBetaRead,
Update: resourceScalewayLbBackendBetaUpdate,
Delete: resourceScalewayLbBackendBetaDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
SchemaVersion: 0,
Schema: map[string]*schema.Schema{
"lb_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The load-balancer id",
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
},
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "The name of the backend",
},
"forward_protocol": {
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
lb.ProtocolTCP.String(),
lb.ProtocolHTTP.String(),
}, false),
Required: true,
Description: "Backend protocol",
},
"forward_port": {
Type: schema.TypeInt,
Required: true,
Description: "User sessions will be forwarded to this port of backend servers",
},
"forward_port_algorithm": {
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
lb.ForwardPortAlgorithmRoundrobin.String(),
lb.ForwardPortAlgorithmLeastconn.String(),
}, false),
Default: lb.ForwardPortAlgorithmRoundrobin.String(),
Optional: true,
Description: "Load balancing algorithm",
},
"sticky_sessions": {
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"none",
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
lb.StickySessionsTypeCookie.String(),
lb.StickySessionsTypeTable.String(),
}, false),
Default: "none",
Optional: true,
Description: "Load balancing algorithm",
},
"sticky_sessions_cookie_name": {
Type: schema.TypeString,
Optional: true,
kindermoumoute marked this conversation as resolved.
Show resolved Hide resolved
Description: "Cookie name for for sticky sessions",
},
"server_ips": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.SingleIP(),
},
Optional: true,
Description: "Backend server IP addresses list (IPv4 or IPv6)",
},
"send_proxy_v2": {
Type: schema.TypeBool,
Description: "Enables PROXY protocol version 2",
Optional: true,
Default: false,
},
"timeout_server": {
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: difSuppressFuncDuration,
ValidateFunc: validateDuration(),
Description: "Maximum server connection inactivity time (in milliseconds).",
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
},
"timeout_connect": {
kindermoumoute marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: difSuppressFuncDuration,
ValidateFunc: validateDuration(),
Description: "Maximum initial server connection establishment time (in milliseconds).",
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
},
"timeout_tunnel": {
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: difSuppressFuncDuration,
ValidateFunc: validateDuration(),
Description: "Maximum tunnel inactivity time (in milliseconds).",
QuentinBrosse marked this conversation as resolved.
Show resolved Hide resolved
},
"on_marked_down_action": {
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"none",
lb.OnMarkedDownActionShutdownSessions.String(),
}, false),
Default: "none",
Optional: true,
jerome-quere marked this conversation as resolved.
Show resolved Hide resolved
Description: "Modify what occurs when a backend server is marked down.",
QuentinBrosse marked this conversation as resolved.
Show resolved Hide resolved
},
},
}
}

func resourceScalewayLbBackendBetaCreate(d *schema.ResourceData, m interface{}) error {
lbAPI := getLbAPI(m)
kindermoumoute marked this conversation as resolved.
Show resolved Hide resolved

region, LbID, err := parseRegionalID(d.Get("lb_id").(string))
if err != nil {
return err
}

name, ok := d.GetOk("name")
if !ok {
name = getRandomName("lb-bkd")
}
createReq := &lb.CreateBackendRequest{
Region: region,
LbID: LbID,
Name: name.(string),
ForwardProtocol: expandLbProtocol(d.Get("forward_protocol")),
ForwardPort: int32(d.Get("forward_port").(int)),
ForwardPortAlgorithm: expandLbForwardPortAlgorithm(d.Get("forward_port_algorithm")),
StickySessions: expandLbStickySessionsType(d.Get("sticky_sessions")),
StickySessionsCookieName: d.Get("sticky_sessions_cookie_name").(string),
HealthCheck: &lb.HealthCheck{
Port: 80,
CheckMaxRetries: 1,
},

QuentinBrosse marked this conversation as resolved.
Show resolved Hide resolved
ServerIP: StringSliceFromState(d.Get("server_ips").([]interface{})),
SendProxyV2: d.Get("send_proxy_v2").(bool),
TimeoutServer: expandDuration(d.Get("timeout_server")),
TimeoutConnect: expandDuration(d.Get("timeout_connect")),
TimeoutTunnel: expandDuration(d.Get("timeout_tunnel")),
OnMarkedDownAction: expandLbBackendMarkdownAction(d.Get("on_marked_down_action")),
}

res, err := lbAPI.CreateBackend(createReq)
if err != nil {
return err
}

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

return resourceScalewayLbBackendBetaRead(d, m)
}

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

res, err := lbAPI.GetBackend(&lb.GetBackendRequest{
Region: region,
BackendID: ID,
})

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

d.Set("lb_id", newRegionalId(region, res.Lb.ID))
d.Set("name", res.Name)
d.Set("forward_protocol", flattenLbProtocol(res.ForwardProtocol))
d.Set("forward_port", res.ForwardPort)
d.Set("forward_port_algorithm", flattenLbForwardPortAlgorithm(res.ForwardPortAlgorithm))
d.Set("sticky_sessions", flattenLbStickySessionsType(res.StickySessions))
d.Set("sticky_sessions_cookie_name", res.StickySessionsCookieName)
d.Set("server_ips", res.Pool)
d.Set("send_proxy_v2", res.SendProxyV2)
d.Set("timeout_server", flattenDuration(res.TimeoutServer))
d.Set("timeout_connect", flattenDuration(res.TimeoutConnect))
d.Set("timeout_tunnel", flattenDuration(res.TimeoutTunnel))
d.Set("on_marked_down_action", flattenLbBackendMarkdownAction(res.OnMarkedDownAction))

return nil
}

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

req := &lb.UpdateBackendRequest{
Region: region,
BackendID: ID,
Name: d.Get("name").(string),
ForwardProtocol: expandLbProtocol(d.Get("forward_protocol")),
ForwardPort: int32(d.Get("forward_port").(int)),
ForwardPortAlgorithm: expandLbForwardPortAlgorithm(d.Get("forward_port_algorithm")),
StickySessions: expandLbStickySessionsType(d.Get("sticky_sessions")),
StickySessionsCookieName: d.Get("sticky_sessions_cookie_name").(string),
SendProxyV2: d.Get("send_proxy_v2").(bool),
TimeoutServer: expandDuration(d.Get("timeout_server")),
TimeoutConnect: expandDuration(d.Get("timeout_connect")),
TimeoutTunnel: expandDuration(d.Get("timeout_tunnel")),
OnMarkedDownAction: expandLbBackendMarkdownAction(d.Get("on_marked_down_action")),
}

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

// Update Backend servers
_, err = lbAPI.SetBackendServers(&lb.SetBackendServersRequest{
Region: region,
BackendID: ID,
ServerIP: StringSliceFromState(d.Get("server_ips").([]interface{})),
})
if err != nil {
return err
}

return resourceScalewayLbBackendBetaRead(d, m)
}

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

err = lbAPI.DeleteBackend(&lb.DeleteBackendRequest{
Region: region,
BackendID: ID,
})

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

if is404Error(err) {
return nil
}

return err
}
Loading