From 7816abfd3940b79dd999c14907a719abc7040dca Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 9 Mar 2015 08:10:23 -0700 Subject: [PATCH] Add dependency on ELB functionality of goamz --- Godeps/Godeps.json | 4 + .../src/github.com/mitchellh/goamz/elb/elb.go | 575 ++++++++++++++++++ .../mitchellh/goamz/elb/elb_test.go | 235 +++++++ .../mitchellh/goamz/elb/responses_test.go | 182 ++++++ .../github.com/mitchellh/goamz/elb/sign.go | 38 ++ 5 files changed, 1034 insertions(+) create mode 100644 Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/goamz/elb/responses_test.go create mode 100644 Godeps/_workspace/src/github.com/mitchellh/goamz/elb/sign.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 67046acf22f..543e848d635 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -189,6 +189,10 @@ "ImportPath": "github.com/mitchellh/goamz/ec2", "Rev": "703cfb45985762869e465f37ed030ff01615ff1e" }, + { + "ImportPath": "github.com/mitchellh/goamz/elb", + "Rev": "703cfb45985762869e465f37ed030ff01615ff1e" + }, { "ImportPath": "github.com/mitchellh/mapstructure", "Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf" diff --git a/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb.go b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb.go new file mode 100644 index 00000000000..e0d53f3879c --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb.go @@ -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 +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb_test.go b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb_test.go new file mode 100644 index 00000000000..d0a5caab618 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/elb_test.go @@ -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") +} diff --git a/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/responses_test.go b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/responses_test.go new file mode 100644 index 00000000000..77ae390cec7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/responses_test.go @@ -0,0 +1,182 @@ +package elb_test + +var ErrorDump = ` + +UnsupportedOperation + +0503f4e9-bbd6-483c-b54f-c4ae9f3b30f4 +` + +// http://goo.gl/OkMdtJ +var AddTagsExample = ` + + + + 360e81f7-1100-11e4-b6ed-0f30EXAMPLE + + +` + +// http://goo.gl/nT2E89 +var RemoveTagsExample = ` + + + + 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE + + +` + +// http://goo.gl/gQRD2H +var CreateLoadBalancerExample = ` + + + MyLoadBalancer-1234567890.us-east-1.elb.amazonaws.com + + + 1549581b-12b7-11e3-895e-1334aEXAMPLE + + +` + +// http://goo.gl/GLZeBN +var DeleteLoadBalancerExample = ` + + + 1549581b-12b7-11e3-895e-1334aEXAMPLE + + +` + +// http://goo.gl/8UgpQ8 +var DescribeLoadBalancersExample = ` + + + + + + MyLoadBalancer + 2013-05-24T21:15:31.280Z + + 90 + HTTP:80/ + 2 + 60 + 10 + + + + + + HTTP + 80 + HTTP + needToAddASSLCertToYourAWSAccount + 80 + + + + + + i-e4cbe38d + + + + + + + + + us-east-1a + + ZZZZZZZZZZZ123X + MyLoadBalancer-123456789.us-east-1.elb.amazonaws.com + internet-facing + + amazon-elb + amazon-elb-sg + + MyLoadBalancer-123456789.us-east-1.elb.amazonaws.com + + + + + + + 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE + + +` + +// http://goo.gl/Uz1N66 +var RegisterInstancesWithLoadBalancerExample = ` + + + + + i-315b7e51 + + + + + 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE + + + ` + +// http://goo.gl/5OMv62 +var DeregisterInstancesFromLoadBalancerExample = ` + + + + + i-6ec63d59 + + + + + 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE + + +` + +// http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/API_ConfigureHealthCheck.html +var ConfigureHealthCheckExample = ` + + + + 30 + HTTP:80/ping + 2 + 3 + 2 + + + + 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE + +` + +// http://goo.gl/cGNxfj +var DescribeInstanceHealthExample = ` + + + + + N/A + i-90d8c2a5 + InService + N/A + + + N/A + i-06ea3e60 + OutOfService + N/A + + + + + 1549581b-12b7-11e3-895e-1334aEXAMPLE + +` diff --git a/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/sign.go b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/sign.go new file mode 100644 index 00000000000..06310304dd2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/mitchellh/goamz/elb/sign.go @@ -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) +}