Merge pull request #5182 from justinsb/aws_bump_goamz

Add dependency on ELB functionality of goamz
pull/6/head
Alex Robinson 2015-03-09 15:49:59 -07:00
commit 828f9eaa7d
5 changed files with 1034 additions and 0 deletions

4
Godeps/Godeps.json generated
View File

@ -189,6 +189,10 @@
"ImportPath": "github.com/mitchellh/goamz/ec2", "ImportPath": "github.com/mitchellh/goamz/ec2",
"Rev": "703cfb45985762869e465f37ed030ff01615ff1e" "Rev": "703cfb45985762869e465f37ed030ff01615ff1e"
}, },
{
"ImportPath": "github.com/mitchellh/goamz/elb",
"Rev": "703cfb45985762869e465f37ed030ff01615ff1e"
},
{ {
"ImportPath": "github.com/mitchellh/mapstructure", "ImportPath": "github.com/mitchellh/mapstructure",
"Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf" "Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf"

View File

@ -0,0 +1,575 @@
// The elb package provides types and functions for interaction with the AWS
// Elastic Load Balancing service (ELB)
package elb
import (
"encoding/xml"
"net/http"
"net/url"
"strconv"
"time"
"github.com/mitchellh/goamz/aws"
)
// The ELB type encapsulates operations operations with the elb endpoint.
type ELB struct {
aws.Auth
aws.Region
httpClient *http.Client
}
const APIVersion = "2012-06-01"
// New creates a new ELB instance.
func New(auth aws.Auth, region aws.Region) *ELB {
return NewWithClient(auth, region, aws.RetryingClient)
}
func NewWithClient(auth aws.Auth, region aws.Region, httpClient *http.Client) *ELB {
return &ELB{auth, region, httpClient}
}
func (elb *ELB) query(params map[string]string, resp interface{}) error {
params["Version"] = APIVersion
params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
endpoint, err := url.Parse(elb.Region.ELBEndpoint)
if err != nil {
return err
}
sign(elb.Auth, "GET", "/", params, endpoint.Host)
endpoint.RawQuery = multimap(params).Encode()
r, err := elb.httpClient.Get(endpoint.String())
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode > 200 {
return buildError(r)
}
decoder := xml.NewDecoder(r.Body)
decodedBody := decoder.Decode(resp)
return decodedBody
}
func buildError(r *http.Response) error {
var (
err Error
errors xmlErrors
)
xml.NewDecoder(r.Body).Decode(&errors)
if len(errors.Errors) > 0 {
err = errors.Errors[0]
}
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
func makeParams(action string) map[string]string {
params := make(map[string]string)
params["Action"] = action
return params
}
// ----------------------------------------------------------------------------
// ELB objects
// A listener attaches to an elb
type Listener struct {
InstancePort int64 `xml:"Listener>InstancePort"`
InstanceProtocol string `xml:"Listener>InstanceProtocol"`
SSLCertificateId string `xml:"Listener>SSLCertificateId"`
LoadBalancerPort int64 `xml:"Listener>LoadBalancerPort"`
Protocol string `xml:"Listener>Protocol"`
}
// An Instance attaches to an elb
type Instance struct {
InstanceId string `xml:"InstanceId"`
}
// A tag attached to an elb
type Tag struct {
Key string `xml:"Key"`
Value string `xml:"Value"`
}
// An InstanceState from an elb health query
type InstanceState struct {
InstanceId string `xml:"InstanceId"`
Description string `xml:"Description"`
State string `xml:"State"`
ReasonCode string `xml:"ReasonCode"`
}
// ----------------------------------------------------------------------------
// AddTags
type AddTags struct {
LoadBalancerNames []string
Tags []Tag
}
type AddTagsResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) AddTags(options *AddTags) (resp *AddTagsResp, err error) {
params := makeParams("AddTags")
for i, v := range options.LoadBalancerNames {
params["LoadBalancerNames.member."+strconv.Itoa(i+1)] = v
}
for i, v := range options.Tags {
params["Tags.member."+strconv.Itoa(i+1)+".Key"] = v.Key
params["Tags.member."+strconv.Itoa(i+1)+".Value"] = v.Value
}
resp = &AddTagsResp{}
err = elb.query(params, resp)
return resp, err
}
// ----------------------------------------------------------------------------
// RemoveTags
type RemoveTags struct {
LoadBalancerNames []string
TagKeys []string
}
type RemoveTagsResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) RemoveTags(options *RemoveTags) (resp *RemoveTagsResp, err error) {
params := makeParams("RemoveTags")
for i, v := range options.LoadBalancerNames {
params["LoadBalancerNames.member."+strconv.Itoa(i+1)] = v
}
for i, v := range options.TagKeys {
params["Tags.member."+strconv.Itoa(i+1)+".Key"] = v
}
resp = &RemoveTagsResp{}
err = elb.query(params, resp)
return resp, err
}
// ----------------------------------------------------------------------------
// Create
// The CreateLoadBalancer request parameters
type CreateLoadBalancer struct {
AvailZone []string
Listeners []Listener
LoadBalancerName string
Internal bool // true for vpc elbs
SecurityGroups []string
Subnets []string
Tags []Tag
}
type CreateLoadBalancerResp struct {
DNSName string `xml:"CreateLoadBalancerResult>DNSName"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) CreateLoadBalancer(options *CreateLoadBalancer) (resp *CreateLoadBalancerResp, err error) {
params := makeParams("CreateLoadBalancer")
params["LoadBalancerName"] = options.LoadBalancerName
for i, v := range options.AvailZone {
params["AvailabilityZones.member."+strconv.Itoa(i+1)] = v
}
for i, v := range options.SecurityGroups {
params["SecurityGroups.member."+strconv.Itoa(i+1)] = v
}
for i, v := range options.Subnets {
params["Subnets.member."+strconv.Itoa(i+1)] = v
}
for i, v := range options.Listeners {
params["Listeners.member."+strconv.Itoa(i+1)+".LoadBalancerPort"] = strconv.FormatInt(v.LoadBalancerPort, 10)
params["Listeners.member."+strconv.Itoa(i+1)+".InstancePort"] = strconv.FormatInt(v.InstancePort, 10)
params["Listeners.member."+strconv.Itoa(i+1)+".Protocol"] = v.Protocol
params["Listeners.member."+strconv.Itoa(i+1)+".InstanceProtocol"] = v.InstanceProtocol
params["Listeners.member."+strconv.Itoa(i+1)+".SSLCertificateId"] = v.SSLCertificateId
}
for i, v := range options.Tags {
params["Tags.member."+strconv.Itoa(i+1)+".Key"] = v.Key
params["Tags.member."+strconv.Itoa(i+1)+".Value"] = v.Value
}
if options.Internal {
params["Scheme"] = "internal"
}
resp = &CreateLoadBalancerResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Destroy
// The DestroyLoadBalancer request parameters
type DeleteLoadBalancer struct {
LoadBalancerName string
}
func (elb *ELB) DeleteLoadBalancer(options *DeleteLoadBalancer) (resp *SimpleResp, err error) {
params := makeParams("DeleteLoadBalancer")
params["LoadBalancerName"] = options.LoadBalancerName
resp = &SimpleResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Describe
// An individual load balancer
type LoadBalancer struct {
LoadBalancerName string `xml:"LoadBalancerName"`
Listeners []Listener `xml:"ListenerDescriptions>member"`
Instances []Instance `xml:"Instances>member"`
HealthCheck HealthCheck `xml:"HealthCheck"`
AvailabilityZones []string `xml:"AvailabilityZones>member"`
HostedZoneNameID string `xml:"CanonicalHostedZoneNameID"`
DNSName string `xml:"DNSName"`
SecurityGroups []string `xml:"SecurityGroups>member"`
Scheme string `xml:"Scheme"`
Subnets []string `xml:"Subnets>member"`
}
// DescribeLoadBalancer request params
type DescribeLoadBalancer struct {
Names []string
}
type DescribeLoadBalancersResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
LoadBalancers []LoadBalancer `xml:"DescribeLoadBalancersResult>LoadBalancerDescriptions>member"`
}
func (elb *ELB) DescribeLoadBalancers(options *DescribeLoadBalancer) (resp *DescribeLoadBalancersResp, err error) {
params := makeParams("DescribeLoadBalancers")
for i, v := range options.Names {
params["LoadBalancerNames.member."+strconv.Itoa(i+1)] = v
}
resp = &DescribeLoadBalancersResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Attributes
type AccessLog struct {
EmitInterval int64
Enabled bool
S3BucketName string
S3BucketPrefix string
}
type ConnectionDraining struct {
Enabled bool
Timeout int64
}
type LoadBalancerAttributes struct {
CrossZoneLoadBalancingEnabled bool
ConnectionSettingsIdleTimeout int64
ConnectionDraining ConnectionDraining
AccessLog AccessLog
}
type ModifyLoadBalancerAttributes struct {
LoadBalancerName string
LoadBalancerAttributes LoadBalancerAttributes
}
func (elb *ELB) ModifyLoadBalancerAttributes(options *ModifyLoadBalancerAttributes) (resp *SimpleResp, err error) {
params := makeParams("ModifyLoadBalancerAttributes")
params["LoadBalancerName"] = options.LoadBalancerName
params["LoadBalancerAttributes.CrossZoneLoadBalancing.Enabled"] = strconv.FormatBool(options.LoadBalancerAttributes.CrossZoneLoadBalancingEnabled)
if options.LoadBalancerAttributes.ConnectionSettingsIdleTimeout > 0 {
params["LoadBalancerAttributes.ConnectionSettings.IdleTimeout"] = strconv.Itoa(int(options.LoadBalancerAttributes.ConnectionSettingsIdleTimeout))
}
if options.LoadBalancerAttributes.ConnectionDraining.Timeout > 0 {
params["LoadBalancerAttributes.ConnectionDraining.Timeout"] = strconv.Itoa(int(options.LoadBalancerAttributes.ConnectionDraining.Timeout))
}
params["LoadBalancerAttributes.ConnectionDraining.Enabled"] = strconv.FormatBool(options.LoadBalancerAttributes.ConnectionDraining.Enabled)
params["LoadBalancerAttributes.AccessLog.Enabled"] = strconv.FormatBool(options.LoadBalancerAttributes.AccessLog.Enabled)
if options.LoadBalancerAttributes.AccessLog.Enabled {
params["LoadBalancerAttributes.AccessLog.EmitInterval"] = strconv.Itoa(int(options.LoadBalancerAttributes.AccessLog.EmitInterval))
params["LoadBalancerAttributes.AccessLog.S3BucketName"] = options.LoadBalancerAttributes.AccessLog.S3BucketName
params["LoadBalancerAttributes.AccessLog.S3BucketPrefix"] = options.LoadBalancerAttributes.AccessLog.S3BucketPrefix
}
resp = &SimpleResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Instance Registration / deregistration
// The RegisterInstancesWithLoadBalancer request parameters
type RegisterInstancesWithLoadBalancer struct {
LoadBalancerName string
Instances []string
}
type RegisterInstancesWithLoadBalancerResp struct {
Instances []Instance `xml:"RegisterInstancesWithLoadBalancerResult>Instances>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) RegisterInstancesWithLoadBalancer(options *RegisterInstancesWithLoadBalancer) (resp *RegisterInstancesWithLoadBalancerResp, err error) {
params := makeParams("RegisterInstancesWithLoadBalancer")
params["LoadBalancerName"] = options.LoadBalancerName
for i, v := range options.Instances {
params["Instances.member."+strconv.Itoa(i+1)+".InstanceId"] = v
}
resp = &RegisterInstancesWithLoadBalancerResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// The DeregisterInstancesFromLoadBalancer request parameters
type DeregisterInstancesFromLoadBalancer struct {
LoadBalancerName string
Instances []string
}
type DeregisterInstancesFromLoadBalancerResp struct {
Instances []Instance `xml:"DeregisterInstancesFromLoadBalancerResult>Instances>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) DeregisterInstancesFromLoadBalancer(options *DeregisterInstancesFromLoadBalancer) (resp *DeregisterInstancesFromLoadBalancerResp, err error) {
params := makeParams("DeregisterInstancesFromLoadBalancer")
params["LoadBalancerName"] = options.LoadBalancerName
for i, v := range options.Instances {
params["Instances.member."+strconv.Itoa(i+1)+".InstanceId"] = v
}
resp = &DeregisterInstancesFromLoadBalancerResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// DescribeTags
type DescribeTags struct {
LoadBalancerNames []string
}
type LoadBalancerTag struct {
Tags []Tag `xml:"Tags>member"`
LoadBalancerName string `xml:"LoadBalancerName"`
}
type DescribeTagsResp struct {
LoadBalancerTags []LoadBalancerTag `xml:"DescribeTagsResult>TagDescriptions>member"`
NextToken string `xml:"DescribeTagsResult>NextToken"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) DescribeTags(options *DescribeTags) (resp *DescribeTagsResp, err error) {
params := makeParams("DescribeTags")
for i, v := range options.LoadBalancerNames {
params["LoadBalancerNames.member."+strconv.Itoa(i+1)] = v
}
resp = &DescribeTagsResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Health Checks
type HealthCheck struct {
HealthyThreshold int64 `xml:"HealthyThreshold"`
UnhealthyThreshold int64 `xml:"UnhealthyThreshold"`
Interval int64 `xml:"Interval"`
Target string `xml:"Target"`
Timeout int64 `xml:"Timeout"`
}
type ConfigureHealthCheck struct {
LoadBalancerName string
Check HealthCheck
}
type ConfigureHealthCheckResp struct {
Check HealthCheck `xml:"ConfigureHealthCheckResult>HealthCheck"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) ConfigureHealthCheck(options *ConfigureHealthCheck) (resp *ConfigureHealthCheckResp, err error) {
params := makeParams("ConfigureHealthCheck")
params["LoadBalancerName"] = options.LoadBalancerName
params["HealthCheck.HealthyThreshold"] = strconv.Itoa(int(options.Check.HealthyThreshold))
params["HealthCheck.UnhealthyThreshold"] = strconv.Itoa(int(options.Check.UnhealthyThreshold))
params["HealthCheck.Interval"] = strconv.Itoa(int(options.Check.Interval))
params["HealthCheck.Target"] = options.Check.Target
params["HealthCheck.Timeout"] = strconv.Itoa(int(options.Check.Timeout))
resp = &ConfigureHealthCheckResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// ----------------------------------------------------------------------------
// Instance Health
// The DescribeInstanceHealth request parameters
type DescribeInstanceHealth struct {
LoadBalancerName string
}
type DescribeInstanceHealthResp struct {
InstanceStates []InstanceState `xml:"DescribeInstanceHealthResult>InstanceStates>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
func (elb *ELB) DescribeInstanceHealth(options *DescribeInstanceHealth) (resp *DescribeInstanceHealthResp, err error) {
params := makeParams("DescribeInstanceHealth")
params["LoadBalancerName"] = options.LoadBalancerName
resp = &DescribeInstanceHealthResp{}
err = elb.query(params, resp)
if err != nil {
resp = nil
}
return
}
// Responses
type SimpleResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
}
type xmlErrors struct {
Errors []Error `xml:"Error"`
}
// Error encapsulates an elb error.
type Error struct {
// HTTP status code of the error.
StatusCode int
// AWS code of the error.
Code string
// Message explaining the error.
Message string
}
func (e *Error) Error() string {
var prefix string
if e.Code != "" {
prefix = e.Code + ": "
}
if prefix == "" && e.StatusCode > 0 {
prefix = strconv.Itoa(e.StatusCode) + ": "
}
return prefix + e.Message
}

View File

@ -0,0 +1,235 @@
package elb_test
import (
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/elb"
"github.com/mitchellh/goamz/testutil"
. "github.com/motain/gocheck"
"testing"
)
func Test(t *testing.T) {
TestingT(t)
}
type S struct {
elb *elb.ELB
}
var _ = Suite(&S{})
var testServer = testutil.NewHTTPServer()
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{"abc", "123", ""}
s.elb = elb.NewWithClient(auth, aws.Region{ELBEndpoint: testServer.URL}, testutil.DefaultClient)
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func (s *S) TestAddTags(c *C) {
testServer.Response(200, nil, AddTagsExample)
options := elb.AddTags{
LoadBalancerNames: []string{"foobar"},
Tags: []elb.Tag{
{
Key: "hello",
Value: "world",
},
},
}
resp, err := s.elb.AddTags(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"AddTags"})
c.Assert(req.Form["LoadBalancerNames.member.1"], DeepEquals, []string{"foobar"})
c.Assert(req.Form["Tags.member.1.Key"], DeepEquals, []string{"hello"})
c.Assert(req.Form["Tags.member.1.Value"], DeepEquals, []string{"world"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "360e81f7-1100-11e4-b6ed-0f30EXAMPLE")
}
func (s *S) TestRemoveTags(c *C) {
testServer.Response(200, nil, RemoveTagsExample)
options := elb.RemoveTags{
LoadBalancerNames: []string{"foobar"},
TagKeys: []string{"hello"},
}
resp, err := s.elb.RemoveTags(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"RemoveTags"})
c.Assert(req.Form["LoadBalancerNames.member.1"], DeepEquals, []string{"foobar"})
c.Assert(req.Form["Tags.member.1.Key"], DeepEquals, []string{"hello"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12EXAMPLE")
}
func (s *S) TestCreateLoadBalancer(c *C) {
testServer.Response(200, nil, CreateLoadBalancerExample)
options := elb.CreateLoadBalancer{
AvailZone: []string{"us-east-1a"},
Listeners: []elb.Listener{elb.Listener{
InstancePort: 80,
InstanceProtocol: "http",
SSLCertificateId: "needToAddASSLCertToYourAWSAccount",
LoadBalancerPort: 80,
Protocol: "http",
},
},
LoadBalancerName: "foobar",
Internal: false,
SecurityGroups: []string{"sg1"},
Subnets: []string{"sn1"},
}
resp, err := s.elb.CreateLoadBalancer(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"CreateLoadBalancer"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "1549581b-12b7-11e3-895e-1334aEXAMPLE")
}
func (s *S) TestDeleteLoadBalancer(c *C) {
testServer.Response(200, nil, DeleteLoadBalancerExample)
options := elb.DeleteLoadBalancer{
LoadBalancerName: "foobar",
}
resp, err := s.elb.DeleteLoadBalancer(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DeleteLoadBalancer"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "1549581b-12b7-11e3-895e-1334aEXAMPLE")
}
func (s *S) TestDescribeLoadBalancers(c *C) {
testServer.Response(200, nil, DescribeLoadBalancersExample)
options := elb.DescribeLoadBalancer{
Names: []string{"foobar"},
}
resp, err := s.elb.DescribeLoadBalancers(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeLoadBalancers"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12EXAMPLE")
c.Assert(resp.LoadBalancers[0].LoadBalancerName, Equals, "MyLoadBalancer")
c.Assert(resp.LoadBalancers[0].Listeners[0].Protocol, Equals, "HTTP")
c.Assert(resp.LoadBalancers[0].Instances[0].InstanceId, Equals, "i-e4cbe38d")
c.Assert(resp.LoadBalancers[0].AvailabilityZones[0].AvailabilityZone, Equals, "us-east-1a")
c.Assert(resp.LoadBalancers[0].Scheme, Equals, "internet-facing")
c.Assert(resp.LoadBalancers[0].DNSName, Equals, "MyLoadBalancer-123456789.us-east-1.elb.amazonaws.com")
c.Assert(resp.LoadBalancers[0].HealthCheck.HealthyThreshold, Equals, int64(2))
c.Assert(resp.LoadBalancers[0].HealthCheck.UnhealthyThreshold, Equals, int64(10))
c.Assert(resp.LoadBalancers[0].HealthCheck.Interval, Equals, int64(90))
c.Assert(resp.LoadBalancers[0].HealthCheck.Target, Equals, "HTTP:80/")
c.Assert(resp.LoadBalancers[0].HealthCheck.Timeout, Equals, int64(60))
}
func (s *S) TestRegisterInstancesWithLoadBalancer(c *C) {
testServer.Response(200, nil, RegisterInstancesWithLoadBalancerExample)
options := elb.RegisterInstancesWithLoadBalancer{
LoadBalancerName: "foobar",
Instances: []string{"instance-1", "instance-2"},
}
resp, err := s.elb.RegisterInstancesWithLoadBalancer(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"RegisterInstancesWithLoadBalancer"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(req.Form["Instances.member.1.InstanceId"], DeepEquals, []string{"instance-1"})
c.Assert(req.Form["Instances.member.2.InstanceId"], DeepEquals, []string{"instance-2"})
c.Assert(err, IsNil)
c.Assert(resp.Instances[0].InstanceId, Equals, "i-315b7e51")
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12EXAMPLE")
}
func (s *S) TestDeregisterInstancesFromLoadBalancer(c *C) {
testServer.Response(200, nil, DeregisterInstancesFromLoadBalancerExample)
options := elb.DeregisterInstancesFromLoadBalancer{
LoadBalancerName: "foobar",
Instances: []string{"instance-1", "instance-2"},
}
resp, err := s.elb.DeregisterInstancesFromLoadBalancer(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DeregisterInstancesFromLoadBalancer"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(req.Form["Instances.member.1.InstanceId"], DeepEquals, []string{"instance-1"})
c.Assert(req.Form["Instances.member.2.InstanceId"], DeepEquals, []string{"instance-2"})
c.Assert(err, IsNil)
c.Assert(resp.Instances[0].InstanceId, Equals, "i-6ec63d59")
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12EXAMPLE")
}
func (s *S) TestConfigureHealthCheck(c *C) {
testServer.Response(200, nil, ConfigureHealthCheckExample)
options := elb.ConfigureHealthCheck{
LoadBalancerName: "foobar",
Check: elb.HealthCheck{
HealthyThreshold: 2,
UnhealthyThreshold: 2,
Interval: 30,
Target: "HTTP:80/ping",
Timeout: 3,
},
}
resp, err := s.elb.ConfigureHealthCheck(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"ConfigureHealthCheck"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(err, IsNil)
c.Assert(resp.Check.HealthyThreshold, Equals, int64(2))
c.Assert(resp.Check.UnhealthyThreshold, Equals, int64(2))
c.Assert(resp.Check.Interval, Equals, int64(30))
c.Assert(resp.Check.Target, Equals, "HTTP:80/ping")
c.Assert(resp.Check.Timeout, Equals, int64(3))
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12EXAMPLE")
}
func (s *S) TestDescribeInstanceHealth(c *C) {
testServer.Response(200, nil, DescribeInstanceHealthExample)
options := elb.DescribeInstanceHealth{
LoadBalancerName: "foobar",
}
resp, err := s.elb.DescribeInstanceHealth(&options)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeInstanceHealth"})
c.Assert(req.Form["LoadBalancerName"], DeepEquals, []string{"foobar"})
c.Assert(err, IsNil)
c.Assert(resp.InstanceStates[0].InstanceId, Equals, "i-90d8c2a5")
c.Assert(resp.InstanceStates[0].State, Equals, "InService")
c.Assert(resp.InstanceStates[1].InstanceId, Equals, "i-06ea3e60")
c.Assert(resp.InstanceStates[1].State, Equals, "OutOfService")
c.Assert(resp.RequestId, Equals, "1549581b-12b7-11e3-895e-1334aEXAMPLE")
}

View File

@ -0,0 +1,182 @@
package elb_test
var ErrorDump = `
<?xml version="1.0" encoding="UTF-8"?>
<Response><Errors><Error><Code>UnsupportedOperation</Code>
<Message></Message>
</Error></Errors><RequestID>0503f4e9-bbd6-483c-b54f-c4ae9f3b30f4</RequestID></Response>
`
// http://goo.gl/OkMdtJ
var AddTagsExample = `
<AddTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<AddTagsResult/>
<ResponseMetadata>
<RequestId>360e81f7-1100-11e4-b6ed-0f30EXAMPLE</RequestId>
</ResponseMetadata>
</AddTagsResponse>
`
// http://goo.gl/nT2E89
var RemoveTagsExample = `
<RemoveTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<RemoveTagsResult/>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</RemoveTagsResponse>
`
// http://goo.gl/gQRD2H
var CreateLoadBalancerExample = `
<CreateLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<CreateLoadBalancerResult>
<DNSName>MyLoadBalancer-1234567890.us-east-1.elb.amazonaws.com</DNSName>
</CreateLoadBalancerResult>
<ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId>
</ResponseMetadata>
</CreateLoadBalancerResponse>
`
// http://goo.gl/GLZeBN
var DeleteLoadBalancerExample = `
<DeleteLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId>
</ResponseMetadata>
</DeleteLoadBalancerResponse>
`
// http://goo.gl/8UgpQ8
var DescribeLoadBalancersExample = `
<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeLoadBalancersResult>
<LoadBalancerDescriptions>
<member>
<SecurityGroups/>
<LoadBalancerName>MyLoadBalancer</LoadBalancerName>
<CreatedTime>2013-05-24T21:15:31.280Z</CreatedTime>
<HealthCheck>
<Interval>90</Interval>
<Target>HTTP:80/</Target>
<HealthyThreshold>2</HealthyThreshold>
<Timeout>60</Timeout>
<UnhealthyThreshold>10</UnhealthyThreshold>
</HealthCheck>
<ListenerDescriptions>
<member>
<PolicyNames/>
<Listener>
<Protocol>HTTP</Protocol>
<LoadBalancerPort>80</LoadBalancerPort>
<InstanceProtocol>HTTP</InstanceProtocol>
<SSLCertificateId>needToAddASSLCertToYourAWSAccount</SSLCertificateId>
<InstancePort>80</InstancePort>
</Listener>
</member>
</ListenerDescriptions>
<Instances>
<member>
<InstanceId>i-e4cbe38d</InstanceId>
</member>
</Instances>
<Policies>
<AppCookieStickinessPolicies/>
<OtherPolicies/>
<LBCookieStickinessPolicies/>
</Policies>
<AvailabilityZones>
<member>us-east-1a</member>
</AvailabilityZones>
<CanonicalHostedZoneNameID>ZZZZZZZZZZZ123X</CanonicalHostedZoneNameID>
<CanonicalHostedZoneName>MyLoadBalancer-123456789.us-east-1.elb.amazonaws.com</CanonicalHostedZoneName>
<Scheme>internet-facing</Scheme>
<SourceSecurityGroup>
<OwnerAlias>amazon-elb</OwnerAlias>
<GroupName>amazon-elb-sg</GroupName>
</SourceSecurityGroup>
<DNSName>MyLoadBalancer-123456789.us-east-1.elb.amazonaws.com</DNSName>
<BackendServerDescriptions/>
<Subnets/>
</member>
</LoadBalancerDescriptions>
</DescribeLoadBalancersResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeLoadBalancersResponse>
`
// http://goo.gl/Uz1N66
var RegisterInstancesWithLoadBalancerExample = `
<RegisterInstancesWithLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<RegisterInstancesWithLoadBalancerResult>
<Instances>
<member>
<InstanceId>i-315b7e51</InstanceId>
</member>
</Instances>
</RegisterInstancesWithLoadBalancerResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</RegisterInstancesWithLoadBalancerResponse>
`
// http://goo.gl/5OMv62
var DeregisterInstancesFromLoadBalancerExample = `
<DeregisterInstancesFromLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DeregisterInstancesFromLoadBalancerResult>
<Instances>
<member>
<InstanceId>i-6ec63d59</InstanceId>
</member>
</Instances>
</DeregisterInstancesFromLoadBalancerResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</DeregisterInstancesFromLoadBalancerResponse>
`
// http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/API_ConfigureHealthCheck.html
var ConfigureHealthCheckExample = `
<ConfigureHealthCheckResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<ConfigureHealthCheckResult>
<HealthCheck>
<Interval>30</Interval>
<Target>HTTP:80/ping</Target>
<HealthyThreshold>2</HealthyThreshold>
<Timeout>3</Timeout>
<UnhealthyThreshold>2</UnhealthyThreshold>
</HealthCheck>
</ConfigureHealthCheckResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</ConfigureHealthCheckResponse>`
// http://goo.gl/cGNxfj
var DescribeInstanceHealthExample = `
<DescribeInstanceHealthResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeInstanceHealthResult>
<InstanceStates>
<member>
<Description>N/A</Description>
<InstanceId>i-90d8c2a5</InstanceId>
<State>InService</State>
<ReasonCode>N/A</ReasonCode>
</member>
<member>
<Description>N/A</Description>
<InstanceId>i-06ea3e60</InstanceId>
<State>OutOfService</State>
<ReasonCode>N/A</ReasonCode>
</member>
</InstanceStates>
</DescribeInstanceHealthResult>
<ResponseMetadata>
<RequestId>1549581b-12b7-11e3-895e-1334aEXAMPLE</RequestId>
</ResponseMetadata>
</DescribeInstanceHealthResponse>`

View File

@ -0,0 +1,38 @@
package elb
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"github.com/mitchellh/goamz/aws"
"sort"
"strings"
)
// ----------------------------------------------------------------------------
// Version 2 signing (http://goo.gl/RSRp5)
var b64 = base64.StdEncoding
func sign(auth aws.Auth, method, path string, params map[string]string, host string) {
params["AWSAccessKeyId"] = auth.AccessKey
params["SignatureVersion"] = "2"
params["SignatureMethod"] = "HmacSHA256"
if auth.Token != "" {
params["SecurityToken"] = auth.Token
}
var sarray []string
for k, v := range params {
sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v))
}
sort.StringSlice(sarray).Sort()
joined := strings.Join(sarray, "&")
payload := method + "\n" + host + "\n" + path + "\n" + joined
hash := hmac.New(sha256.New, []byte(auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}