Skip to content

Commit

Permalink
Merge pull request #132 from yunify/add-loadbalancer-backend
Browse files Browse the repository at this point in the history
Add loadbalancer backend
  • Loading branch information
runzexia authored Jan 9, 2018
2 parents 232d38c + f8bffb0 commit ec5979c
Show file tree
Hide file tree
Showing 53 changed files with 1,364 additions and 178 deletions.
6 changes: 4 additions & 2 deletions qingcloud/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ const (
qingcloudResourceTypeRouter = "router"
qingcloudResourceTypeLoadBalancer = "loadbalancer"

DEFAULT_ZONE = "pek3a"
DEFAULT_ENDPOINT = "https://api.qingcloud.com:443/iaas"
DEFAULT_ZONE = "pek3a"
DEFAULT_ENDPOINT = "https://api.qingcloud.com:443/iaas"
waitJobTimeOutDefault = 120
waitJobIntervalDefault = 5

resourceName = "name"
resourceDescription = "description"
Expand Down
1 change: 1 addition & 0 deletions qingcloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func Provider() terraform.ResourceProvider {
"qingcloud_vpc_static": resourceQingcloudVpcStatic(),
"qingcloud_loadbalancer": resourceQingcloudLoadBalancer(),
"qingcloud_loadbalancer_listener": resourceQingcloudLoadBalancerListener(),
"qingcloud_loadbalancer_backend": resourceQingcloudLoadBalancerBackend(),
"qingcloud_server_certificate": resourceQingcloudServerCertificate(),
},
ConfigureFunc: providerConfigure,
Expand Down
2 changes: 1 addition & 1 deletion qingcloud/resource_qingcloud_eip.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func resourceQingcloudEipDelete(d *schema.ResourceData, meta interface{}) error
}
client.WaitJob(meta.(*QingCloudClient).job,
qc.StringValue(output.JobID),
time.Duration(10)*time.Second, time.Duration(1)*time.Second)
time.Duration(waitJobTimeOutDefault)*time.Second, time.Duration(waitJobIntervalDefault)*time.Second)
d.SetId("")
return nil
}
170 changes: 170 additions & 0 deletions qingcloud/resource_qingcloud_loadbalancer_backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package qingcloud

import (
"github.com/hashicorp/terraform/helper/schema"
qc "github.com/yunify/qingcloud-sdk-go/service"
)

const (
resourceLoadBalancerBackendResrourceId = "resource_id"
resourceLoadBalancerBackendPort = "port"
resourceLoadBalancerBackendWeight = "weight"
resourceLoadBalancerBackendListenerId = "loadbalancer_listener_id"
)

func resourceQingcloudLoadBalancerBackend() *schema.Resource {

return &schema.Resource{
Create: resourceQingcloudLoadBalancerBackendCreate,
Read: resourceQingcloudLoadBalancerBackendRead,
Update: resourceQingcloudLoadBalancerBackendUpdate,
Delete: resourceQingcloudLoadBalancerBackendDelete,
Schema: map[string]*schema.Schema{
resourceName: &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
resourceLoadBalancerBackendResrourceId: &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
resourceLoadBalancerBackendPort: &schema.Schema{
Type: schema.TypeInt,
Required: true,
ValidateFunc: withinArrayIntRange(1, 65535),
},
resourceLoadBalancerBackendListenerId: &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
resourceLoadBalancerBackendWeight: &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 1,
ValidateFunc: withinArrayIntRange(1, 100),
},
},
}
}
func resourceQingcloudLoadBalancerBackendCreate(d *schema.ResourceData, meta interface{}) error {
clt := meta.(*QingCloudClient).loadbalancer
input := new(qc.AddLoadBalancerBackendsInput)
lbe := new(qc.LoadBalancerBackend)
lbe.LoadBalancerListenerID = getSetStringPointer(d, resourceLoadBalancerBackendListenerId)
lbe.Port = qc.Int(d.Get(resourceLoadBalancerBackendPort).(int))
lbe.LoadBalancerBackendName = getSetStringPointer(d, resourceName)
lbe.ResourceID = getSetStringPointer(d, resourceLoadBalancerBackendResrourceId)
lbe.Weight = qc.Int(d.Get(resourceLoadBalancerBackendWeight).(int))
input.Backends = []*qc.LoadBalancerBackend{lbe}
input.LoadBalancerListener = getSetStringPointer(d, resourceLoadBalancerBackendListenerId)
var output *qc.AddLoadBalancerBackendsOutput
var err error
simpleRetry(func() error {
output, err = clt.AddLoadBalancerBackends(input)
return isServerBusy(err)
})
if err != nil {
return err
}
lbId, err := getLBIdFromLBB(output.LoadBalancerBackends[0], meta)
if err != nil {
return err
}
if err := updateLoadBalancer(lbId, meta); err != nil {
return nil
}
d.SetId(qc.StringValue(output.LoadBalancerBackends[0]))
return resourceQingcloudLoadBalancerBackendRead(d, meta)
}
func resourceQingcloudLoadBalancerBackendDelete(d *schema.ResourceData, meta interface{}) error {
clt := meta.(*QingCloudClient).loadbalancer
var output *qc.DeleteLoadBalancerBackendsOutput
var err error
lbId, err := getLBIdFromLBB(qc.String(d.Id()), meta)
if err != nil {
return err
}
input := new(qc.DeleteLoadBalancerBackendsInput)
input.LoadBalancerBackends = []*string{qc.String(d.Id())}
simpleRetry(func() error {
output, err = clt.DeleteLoadBalancerBackends(input)
return isServerBusy(err)
})
if err != nil {
return err
}
if err := updateLoadBalancer(lbId, meta); err != nil {
return nil
}
d.SetId("")
return nil

}
func resourceQingcloudLoadBalancerBackendRead(d *schema.ResourceData, meta interface{}) error {
clt := meta.(*QingCloudClient).loadbalancer
input := new(qc.DescribeLoadBalancerBackendsInput)
input.LoadBalancerBackends = []*string{qc.String(d.Id())}
input.LoadBalancerListener = getSetStringPointer(d, resourceLoadBalancerBackendListenerId)
var output *qc.DescribeLoadBalancerBackendsOutput
var err error
simpleRetry(func() error {
output, err = clt.DescribeLoadBalancerBackends(input)
return isServerBusy(err)
})
if err != nil {
return err
}
if len(output.LoadBalancerBackendSet) == 0 {
d.SetId("")
return nil
}
d.Set(resourceName, qc.StringValue(output.LoadBalancerBackendSet[0].LoadBalancerBackendName))
d.Set(resourceLoadBalancerBackendResrourceId, qc.StringValue(output.LoadBalancerBackendSet[0].ResourceID))
d.Set(resourceLoadBalancerBackendListenerId, qc.StringValue(output.LoadBalancerBackendSet[0].LoadBalancerListenerID))
d.Set(resourceLoadBalancerBackendPort, qc.IntValue(output.LoadBalancerBackendSet[0].Port))
d.Set(resourceLoadBalancerBackendWeight, qc.IntValue(output.LoadBalancerBackendSet[0].Weight))
return nil
}

func resourceQingcloudLoadBalancerBackendUpdate(d *schema.ResourceData, meta interface{}) error {
clt := meta.(*QingCloudClient).loadbalancer
input := new(qc.ModifyLoadBalancerBackendAttributesInput)
input.LoadBalancerBackend = qc.String(d.Id())
input.Weight = qc.Int(d.Get(resourceLoadBalancerBackendWeight).(int))
input.Port = qc.Int(d.Get(resourceLoadBalancerBackendPort).(int))
input.LoadBalancerBackendName = getUpdateStringPointer(d, resourceName)

var output *qc.ModifyLoadBalancerBackendAttributesOutput
var err error
simpleRetry(func() error {
output, err = clt.ModifyLoadBalancerBackendAttributes(input)
return isServerBusy(err)
})
if err != nil {
return err
}
if err := updateLoadBalancer(qc.String(d.Get(resourceLoadBalancerBackendListenerId).(string)), meta); err != nil {
return nil
}
return resourceQingcloudLoadBalancerListenerRead(d, meta)

}

func getLBIdFromLBB(lbbId *string, meta interface{}) (*string, error) {
clt := meta.(*QingCloudClient).loadbalancer
input := new(qc.DescribeLoadBalancerBackendsInput)
input.Verbose = qc.Int(1)
input.LoadBalancerBackends = []*string{lbbId}
var output *qc.DescribeLoadBalancerBackendsOutput
var err error
simpleRetry(func() error {
output, err = clt.DescribeLoadBalancerBackends(input)
return isServerBusy(err)
})
if err != nil {
return nil, err
}
return output.LoadBalancerBackendSet[0].LoadBalancerID, nil
}
172 changes: 172 additions & 0 deletions qingcloud/resource_qingcloud_loadbalancer_backend_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package qingcloud

import (
"fmt"
"log"
"os"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
qc "github.com/yunify/qingcloud-sdk-go/service"
)

func TestAccQingcloudLoadBalancerBackend_basic(t *testing.T) {
var lbb qc.DescribeLoadBalancerBackendsOutput
testTag := "terraform-test-lb-backend-basic" + os.Getenv("CIRCLE_BUILD_NUM")

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},

IDRefreshName: "qingcloud_loadbalancer_backend.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckLoadBalancerBackendDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: fmt.Sprintf(testAccLBBConfigBasic, testTag),
Check: resource.ComposeTestCheckFunc(
testAccCheckLoadBalancerBackendExists(
"qingcloud_loadbalancer_backend.foo", &lbb),
resource.TestCheckResourceAttr("qingcloud_loadbalancer_backend.foo", "port", "80"),
resource.TestCheckResourceAttr("qingcloud_loadbalancer_backend.foo", "weight", "1"),
),
},
resource.TestStep{
Config: fmt.Sprintf(testAccLBBConfigBasicTwo, testTag),
Check: resource.ComposeTestCheckFunc(
testAccCheckLoadBalancerBackendExists(
"qingcloud_loadbalancer_backend.foo", &lbb),
resource.TestCheckResourceAttr("qingcloud_loadbalancer_backend.foo", "port", "81"),
resource.TestCheckResourceAttr("qingcloud_loadbalancer_backend.foo", "weight", "2"),
resource.TestCheckResourceAttr("qingcloud_loadbalancer_backend.foo", "name", "test")),
},
},
})
}

func testAccCheckLoadBalancerBackendDestroy(s *terraform.State) error {
return testAccCheckLoadBalancerBackendDestroyWithProvider(s, testAccProvider)
}

func testAccCheckLoadBalancerBackendDestroyWithProvider(s *terraform.State, provider *schema.Provider) error {
client := provider.Meta().(*QingCloudClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "qingcloud_loadbalancer_backend" {
continue
}
input := new(qc.DescribeLoadBalancerBackendsInput)
input.LoadBalancerBackends = []*string{qc.String(rs.Primary.ID)}
output, err := client.loadbalancer.DescribeLoadBalancerBackends(input)
if err == nil {
if len(output.LoadBalancerBackendSet) != 0 {
return fmt.Errorf("fount loadbalancer backend: %s", rs.Primary.ID)
}
}
}
return nil
}

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

if rs.Primary.ID == "" {
return fmt.Errorf("no loadbalancer backend ID is set")
}

client := testAccProvider.Meta().(*QingCloudClient)
input := new(qc.DescribeLoadBalancerBackendsInput)
input.Verbose = qc.Int(1)
input.LoadBalancerBackends = []*string{qc.String(rs.Primary.ID)}
d, err := client.loadbalancer.DescribeLoadBalancerBackends(input)

log.Printf("[WARN] loadbalancer backend id %#v", rs.Primary.ID)

if err != nil {
return err
}

if d == nil || len(d.LoadBalancerBackendSet) == 0 {
return fmt.Errorf("Lb backend not found ")
}

*i = *d
return nil
}
}

const testAccLBBConfigBasic = `
resource "qingcloud_eip" "foo" {
bandwidth = 2
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_loadbalancer" "foo" {
eip_ids =["${qingcloud_eip.foo.id}"]
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_tag" "test"{
name="%v"
}
resource "qingcloud_loadbalancer_listener" "foo"{
load_balancer_id = "${qingcloud_loadbalancer.foo.id}"
listener_port = "80"
listener_protocol = "http"
}
resource "qingcloud_instance" "foo" {
image_id = "centos7x64d"
keypair_ids = ["${qingcloud_keypair.foo.id}"]
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_loadbalancer_backend" "foo" {
loadbalancer_listener_id = "${qingcloud_loadbalancer_listener.foo.id}"
port = 80
resource_id = "${qingcloud_instance.foo.id}"
}
resource "qingcloud_keypair" "foo"{
public_key = " ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyLSPqVIdXGH0QlGeWcPwa1fjTRKl6WtMiaSsP8/GnwjakDSKILUCoNe1yIpiK8F0/gmL71xaDQyfl7k6aE+gn6lSLUjpDmucAF1luGg6l7CIN+6hCqY3YqlAI05Tqwu0PdLAwCbGwdHcaWfECcbROJk5D0zpCTHmissrrAxdOv72g9Ple8KJ6C7F1tz6wmG0zUeineguGjW/PvfZiBDWZ/CyXGPeMDJxv3lrIiLa/ShgnQOxFTdHJPCw+F0/XlSzlIzP3gfni1vXxJWvYjdE9ULo7Z1DLWgZ73FCbeAvX/0e9C9jwT21Qa5RUy4pSP8m4WXSJgw2f9IpY1vIJFSZP root@centos1 "
tag_ids = ["${qingcloud_tag.test.id}"]
}
`
const testAccLBBConfigBasicTwo = `
resource "qingcloud_eip" "foo" {
bandwidth = 2
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_loadbalancer" "foo" {
eip_ids =["${qingcloud_eip.foo.id}"]
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_tag" "test"{
name="%v"
}
resource "qingcloud_loadbalancer_listener" "foo"{
load_balancer_id = "${qingcloud_loadbalancer.foo.id}"
listener_port = "80"
listener_protocol = "http"
}
resource "qingcloud_instance" "foo" {
image_id = "centos7x64d"
keypair_ids = ["${qingcloud_keypair.foo.id}"]
tag_ids = ["${qingcloud_tag.test.id}"]
}
resource "qingcloud_loadbalancer_backend" "foo" {
loadbalancer_listener_id = "${qingcloud_loadbalancer_listener.foo.id}"
port = 81
resource_id = "${qingcloud_instance.foo.id}"
weight = 2
name = "test"
}
resource "qingcloud_keypair" "foo"{
public_key = " ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyLSPqVIdXGH0QlGeWcPwa1fjTRKl6WtMiaSsP8/GnwjakDSKILUCoNe1yIpiK8F0/gmL71xaDQyfl7k6aE+gn6lSLUjpDmucAF1luGg6l7CIN+6hCqY3YqlAI05Tqwu0PdLAwCbGwdHcaWfECcbROJk5D0zpCTHmissrrAxdOv72g9Ple8KJ6C7F1tz6wmG0zUeineguGjW/PvfZiBDWZ/CyXGPeMDJxv3lrIiLa/ShgnQOxFTdHJPCw+F0/XlSzlIzP3gfni1vXxJWvYjdE9ULo7Z1DLWgZ73FCbeAvX/0e9C9jwT21Qa5RUy4pSP8m4WXSJgw2f9IpY1vIJFSZP root@centos1 "
tag_ids = ["${qingcloud_tag.test.id}"]
}
`
4 changes: 2 additions & 2 deletions qingcloud/resource_qingcloud_loadbalancer_help.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func updateLoadBalancer(lbID *string, meta interface{}) error {
}
client.WaitJob(meta.(*QingCloudClient).job,
qc.StringValue(output.JobID),
time.Duration(10)*time.Second, time.Duration(1)*time.Second)
time.Duration(waitJobTimeOutDefault)*time.Second, time.Duration(waitJobIntervalDefault)*time.Second)
if _, err := LoadBalancerTransitionStateRefresh(clt, lbID); err != nil {
return err
}
Expand Down Expand Up @@ -93,7 +93,7 @@ func dissociateEipsToLoadBalancer(lbID *string, eips []*string, meta interface{}
}
client.WaitJob(meta.(*QingCloudClient).job,
qc.StringValue(output.JobID),
time.Duration(10)*time.Minute, time.Duration(5)*time.Second)
time.Duration(waitJobTimeOutDefault)*time.Minute, time.Duration(waitJobIntervalDefault)*time.Second)
if _, err := LoadBalancerTransitionStateRefresh(clt, lbID); err != nil {
return err
}
Expand Down
Loading

0 comments on commit ec5979c

Please sign in to comment.