Merge lp:~dimitern/goamz/update-aws-api-version-to-latest into lp:goamz

Proposed by Dimiter Naydenov
Status: Rejected
Rejected by: Dimiter Naydenov
Proposed branch: lp:~dimitern/goamz/update-aws-api-version-to-latest
Merge into: lp:goamz
Diff against target: 1025 lines (+180/-171)
12 files modified
ec2/ec2.go (+24/-45)
ec2/ec2_test.go (+14/-11)
ec2/ec2i_test.go (+6/-6)
ec2/ec2t_test.go (+95/-76)
ec2/ec2test/server.go (+16/-12)
ec2/export_test.go (+0/-2)
ec2/networkinterfaces.go (+5/-5)
ec2/networkinterfaces_test.go (+7/-4)
ec2/privateips.go (+2/-2)
ec2/privateips_test.go (+5/-2)
ec2/subnets.go (+3/-3)
ec2/vpc.go (+3/-3)
To merge this branch: bzr merge lp:~dimitern/goamz/update-aws-api-version-to-latest
Reviewer Review Type Date Requested Status
Michael Foord (community) Approve
Martin Packman (community) Approve
Review via email: mp+243057@code.launchpad.net

Description of the change

Updated AWS API version used by default to the latest available (2014-10-01)
This simplifies a few places in the code, and also addresses bug #1394186

A few drive-by fixes were done as well, to ensure the ec2test server reacts the same way as live EC2

Summary of more important changes:
- CreateSecurityGroupVPC method is gone (it was a workaround anyway); now CreateSecurityGroup takes an optional vpcId argument like the *VPC() version used to
- When ec2's debug flag is true, now requests are printed before the responses;
- Fixed the serialization format for SecurityGroup's IPPerm component - SourceIPs is now a slice of CIDRIP{IP:string} structs, so it gets properly serialized to match live EC2;
- In the live tests changed the AZ used for test subnets, as the instance types used there (t1-micro and m1-medium) were not available in us-east-1e AZ (which causes live tests to fail randomly)
- Updated ec2test server's error responses in a few cases to match EC2

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

Change looks good - the complication is this *is* an api breakage so will require the use of a versioned api bump or similar to have distribution beyond juju. We can just pin as needed with dependencies.tsv so it's fine for our usage.

A few comments inline:

review: Approve
Revision history for this message
Michael Foord (mfoord) wrote :

So long as we can live the incompatible changes to the security groups api it looks fine.

review: Approve
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Two comments were already made highlighting the issue of incompatibility, and despite it both of them are approving the change, and no further comments were made about it here. I find that slightly surprising, as it's obvious that the change will break existing code for people relying on it, both inside Canonical and outside. Note also that when you bump an API like this, it is possible that the same operations now have different outcomes, and the fact you had to fix the live tests, per the commit log, seems to indicate that this is happening.

So considering that the juju team is responsible for that package, what is your approach to backwards compatibility, and what's the plan now and for the future?

Also, have you reviewed the change log to consider whether this change might break existing clients due to subtle behavior change in existing operations? Tests will most likely not get all of these cases.

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Thanks for all the reviews!

Now that goamz is migrated to github I'm analyzing how upgrading the AWS API version will affect juju-core's use of goamz and will repropose this against gopkg.in/amz.v2-dev branch. If all goes well, v2-dev could be "promoted" to v2 and juju-core can start using it.

Revision history for this message
Dimiter Naydenov (dimitern) wrote :
Download full text (3.2 KiB)

I've done a careful analysis of the following 3 AWS API versions: 2011-12-15 (used for all non-VPC calls), 2013-10-15 (used for VPC calls), 2014-10-01 (current latest version), using the published AWS WSDL schemas to determine how upgrading the version will impact juju-core's usage of goamz.

Fortunately, there are not many changes and very few, easily fixable changes affect juju-core:

VPC calls with no changes in 2014-10-01 vs 2013-10-15:

AssignPrivateIpAddresses
AttachNetworkInterface
CreateNetworkInterface
CreateSecurityGroup
CreateSubnet
CreateVpc
DeleteNetworkInterface
DeleteSubnet
DeleteVpc
DescribeAccountAttributes
DescribeNetworkInterfaces
DescribeSubnets
DescribeVpcs
DetachNetworkInterface
UnassignPrivateIpAddresses

non-VPC calls with no changes in 2014-10-01 vs 2011-12-15:

AuthorizeSecurityGroupIngress
CreateSnapshot
CreateTags
DeleteSnapshot
DescribeAvailabilityZones
DescribeSecurityGroups
DescribeSnapshots
RebootInstances
RevokeSecurityGroupIngress
StartInstances
StopInstances
TerminateInstances

non-VPC calls with changes between 2011-12-15 and 2014-10-01:

DescribeInstances
    request changes:
        maxResults, nextToken (added - not supported or used by juju; pagination support)
    response changes:
        instancesSet>item>productCodes>item>type (added - not supported or used by juju-core)
        instancesSet>item>iamInstanceProfile>* (added whole subtree - not supported or used by juju-core)
        instancesSet>item>ebsOptimized (added - not supported but needed for storage work in juju-core)
        instancesSet>item>sriovNetSupport (added - not supported or used by juju-core)
        instancesSet>item>networkInterfaceSet>item>macAddress (added - already supported since VPC calls landed)
        instancesSet>item>networkInterfaceSet>item>association>* (added whole subtree - not used by juju-core; related to elastic IPs)
        instancesSet>item>networkInterfaceSet>item>privateIpAddressesSet>* (added whole subtree - already supported since VPC calls landed; >item>association>* not supported, but not used as well)
        nextToken (added - not supported or used by juju; for pagination of results)
RunInstances
    request changes:
        blockDeviceMapping>item>ebs>volumeType (added - already supported since storage changes landed)
        blockDeviceMapping>item>ebs>iops (added - already supported since storage changes)
        networkInterfaceSet>item>* - same changes as in DescribeInstances, except:
        networkInterfaceSet>item>associatePublicIpAddress (added - not supported but needed by juju)
        iamInstanceProfile>* (added whole subtree - not supported or used by juju)
        ebsOptimized (added - not supported but possibly needed for juju storage work)
    response changes: the same as for DescribeInstances, except for nextToken

DescribeImages
    request - no changes
    response changes:
        sriovNetSupport (added - not supported or used by juju)
        productCodes, blockDeviceMapping (added - same changes as in RunInstances)

So overall upgrading AWS API version to 2014-10-01 won't require changes in juju-core, and only a few changes to add what's missing in the request/response structs,...

Read more...

Unmerged revisions

51. By Dimiter Naydenov

Upgraded AWS API version to latest - 2014-10-01; live tests pass OK

50. By Dimiter Naydenov

All live tests fixed; using the latest API version now

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ec2/ec2.go'
2--- ec2/ec2.go 2014-08-11 22:08:47 +0000
3+++ ec2/ec2.go 2014-11-27 15:29:26 +0000
4@@ -10,6 +10,7 @@
5
6 import (
7 "crypto/rand"
8+ "encoding/base64"
9 "encoding/hex"
10 "encoding/xml"
11 "fmt"
12@@ -21,19 +22,14 @@
13 "strconv"
14 "time"
15
16- "encoding/base64"
17 "launchpad.net/goamz/aws"
18 )
19
20 const (
21 debug = false
22
23- // legacyAPIVersion is the AWS API version used for all but
24- // VPC-related requests.
25- legacyAPIVersion = "2011-12-15"
26-
27- // AWS API version used for VPC-related calls.
28- vpcAPIVersion = "2013-10-15"
29+ // apiVersion is the AWS API version used for all requests.
30+ apiVersion = "2014-10-01"
31 )
32
33 // The EC2 type encapsulates operations with a specific EC2 region.
34@@ -152,7 +148,10 @@
35 defer r.Body.Close()
36
37 if debug {
38- dump, _ := httputil.DumpResponse(r, true)
39+ dump, _ := httputil.DumpRequest(req, true)
40+ log.Printf("request:\n")
41+ log.Printf("%v\n}\n", string(dump))
42+ dump, _ = httputil.DumpResponse(r, true)
43 log.Printf("response:\n")
44 log.Printf("%v\n}\n", string(dump))
45 }
46@@ -186,17 +185,9 @@
47 }
48
49 func makeParams(action string) map[string]string {
50- return makeParamsWithVersion(action, legacyAPIVersion)
51-}
52-
53-func makeParamsVPC(action string) map[string]string {
54- return makeParamsWithVersion(action, vpcAPIVersion)
55-}
56-
57-func makeParamsWithVersion(action, version string) map[string]string {
58 params := make(map[string]string)
59 params["Action"] = action
60- params["Version"] = version
61+ params["Version"] = apiVersion
62 return params
63 }
64
65@@ -309,7 +300,7 @@
66 //
67 // See http://goo.gl/Mcm3b for more details.
68 func (ec2 *EC2) RunInstances(options *RunInstances) (resp *RunInstancesResp, err error) {
69- params := prepareRunParams(*options)
70+ params := makeParams("RunInstances")
71 params["ImageId"] = options.ImageId
72 params["InstanceType"] = options.InstanceType
73 var min, max int
74@@ -387,16 +378,6 @@
75 return
76 }
77
78-func prepareRunParams(options RunInstances) map[string]string {
79- if options.SubnetId != "" || len(options.NetworkInterfaces) > 0 {
80- // When either SubnetId or NetworkInterfaces are specified, we
81- // need to use the API version with complete VPC support.
82- return makeParamsVPC("RunInstances")
83- } else {
84- return makeParams("RunInstances")
85- }
86-}
87-
88 func prepareBlockDevices(params map[string]string, blockDevs []BlockDeviceMapping) {
89 for i, b := range blockDevs {
90 n := strconv.Itoa(i + 1)
91@@ -731,20 +712,12 @@
92 }
93
94 // CreateSecurityGroup creates a security group with the provided name
95-// and description.
96-//
97-// See http://goo.gl/Eo7Yl for more details.
98-func (ec2 *EC2) CreateSecurityGroup(name, description string) (resp *CreateSecurityGroupResp, err error) {
99- return ec2.CreateSecurityGroupVPC("", name, description)
100-}
101-
102-// CreateSecurityGroupVPC creates a security group in EC2, associated
103-// with the given VPC ID. If vpcId is empty, this call is equivalent
104-// to CreateSecurityGroup.
105-//
106-// See http://goo.gl/Eo7Yl for more details.
107-func (ec2 *EC2) CreateSecurityGroupVPC(vpcId, name, description string) (resp *CreateSecurityGroupResp, err error) {
108- params := makeParamsVPC("CreateSecurityGroup")
109+// and description. If vpcId can be empty to create a EC2-Classic
110+// group.
111+//
112+// See http://goo.gl/Eo7Yl for more details.
113+func (ec2 *EC2) CreateSecurityGroup(vpcId, name, description string) (resp *CreateSecurityGroupResp, err error) {
114+ params := makeParams("CreateSecurityGroup")
115 params["GroupName"] = name
116 params["GroupDescription"] = description
117 if vpcId != "" {
118@@ -780,6 +753,12 @@
119 IPPerms []IPPerm `xml:"ipPermissions>item"`
120 }
121
122+// CIDRIP represents a single source address in CIDR notation (e.g.
123+// 1.2.3.4/5), used in a security group IPPerm rule.
124+type CIDRIP struct {
125+ IP string `xml:"cidrIp"`
126+}
127+
128 // IPPerm represents an allowance within an EC2 security group.
129 //
130 // See http://goo.gl/4oTxv for more details.
131@@ -787,7 +766,7 @@
132 Protocol string `xml:"ipProtocol"`
133 FromPort int `xml:"fromPort"`
134 ToPort int `xml:"toPort"`
135- SourceIPs []string `xml:"ipRanges>item>cidrIp"`
136+ SourceIPs []CIDRIP `xml:"ipRanges>item"`
137 SourceGroups []UserSecurityGroup `xml:"groups>item"`
138 }
139
140@@ -902,7 +881,7 @@
141 params[prefix+".FromPort"] = strconv.Itoa(perm.FromPort)
142 params[prefix+".ToPort"] = strconv.Itoa(perm.ToPort)
143 for j, ip := range perm.SourceIPs {
144- params[prefix+".IpRanges."+strconv.Itoa(j+1)+".CidrIp"] = ip
145+ params[prefix+".IpRanges."+strconv.Itoa(j+1)+".CidrIp"] = ip.IP
146 }
147 for j, g := range perm.SourceGroups {
148 subprefix := prefix + ".Groups." + strconv.Itoa(j+1)
149@@ -1078,7 +1057,7 @@
150 //
151 // See http://goo.gl/hBc28j for more details.
152 func (ec2 *EC2) AccountAttributes(attrNames ...string) (*AccountAttributesResp, error) {
153- params := makeParamsVPC("DescribeAccountAttributes")
154+ params := makeParams("DescribeAccountAttributes")
155 for i, attrName := range attrNames {
156 params["AttributeName."+strconv.Itoa(i+1)] = attrName
157 }
158
159=== modified file 'ec2/ec2_test.go'
160--- ec2/ec2_test.go 2014-08-11 22:08:47 +0000
161+++ ec2/ec2_test.go 2014-11-27 15:29:26 +0000
162@@ -3,10 +3,10 @@
163 import (
164 "testing"
165
166+ . "gopkg.in/check.v1"
167 "launchpad.net/goamz/aws"
168 "launchpad.net/goamz/ec2"
169 "launchpad.net/goamz/testutil"
170- . "gopkg.in/check.v1"
171 )
172
173 func Test(t *testing.T) {
174@@ -128,11 +128,6 @@
175 }},
176 }},
177 }
178- params := ec2.PrepareRunParams(options)
179- c.Assert(params, DeepEquals, map[string]string{
180- "Version": "2013-10-15",
181- "Action": "RunInstances",
182- })
183 resp, err := s.ec2.RunInstances(&options)
184
185 req := testServer.WaitRequest()
186@@ -503,12 +498,12 @@
187
188 func (s *S) TestCreateSecurityGroupExample(c *C) {
189 testServer.Response(200, nil, CreateSecurityGroupExample)
190- resp, err := s.ec2.CreateSecurityGroup("websrv", "Web Servers")
191+ resp, err := s.ec2.CreateSecurityGroup("", "websrv", "Web Servers")
192 c.Assert(err, IsNil)
193 s.checkCreateSGResponse(c, resp, "sg-67ad940e", "websrv", "Web Servers", "")
194
195 testServer.Response(200, nil, CreateSecurityGroupExample)
196- resp, err = s.ec2.CreateSecurityGroupVPC("vpc-id", "websrv", "Web Servers")
197+ resp, err = s.ec2.CreateSecurityGroup("vpc-id", "websrv", "Web Servers")
198 c.Assert(err, IsNil)
199 s.checkCreateSGResponse(c, resp, "sg-67ad940e", "websrv", "Web Servers", "vpc-id")
200 }
201@@ -538,7 +533,7 @@
202 c.Assert(g0ipp.Protocol, Equals, "tcp")
203 c.Assert(g0ipp.FromPort, Equals, 80)
204 c.Assert(g0ipp.ToPort, Equals, 80)
205- c.Assert(g0ipp.SourceIPs, DeepEquals, []string{"0.0.0.0/0"})
206+ c.Assert(g0ipp.SourceIPs, DeepEquals, sourceIPs("0.0.0.0/0"))
207
208 g1 := resp.Groups[1]
209 c.Assert(g1.OwnerId, Equals, "999988887777")
210@@ -632,6 +627,14 @@
211 c.Assert(req.Form["GroupId"], DeepEquals, []string{"sg-67ad940e"})
212 }
213
214+func sourceIPs(ips ...string) []ec2.CIDRIP {
215+ result := make([]ec2.CIDRIP, len(ips))
216+ for i, ip := range ips {
217+ result[i].IP = ip
218+ }
219+ return result
220+}
221+
222 func (s *S) TestAuthorizeSecurityGroupExample1(c *C) {
223 testServer.Response(200, nil, AuthorizeSecurityGroupIngressExample)
224
225@@ -639,7 +642,7 @@
226 Protocol: "tcp",
227 FromPort: 80,
228 ToPort: 80,
229- SourceIPs: []string{"205.192.0.0/16", "205.159.0.0/16"},
230+ SourceIPs: sourceIPs("205.192.0.0/16", "205.159.0.0/16"),
231 }}
232 resp, err := s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: "websrv"}, perms)
233
234@@ -664,7 +667,7 @@
235 Protocol: "tcp",
236 FromPort: 80,
237 ToPort: 80,
238- SourceIPs: []string{"205.192.0.0/16", "205.159.0.0/16"},
239+ SourceIPs: sourceIPs("205.192.0.0/16", "205.159.0.0/16"),
240 }}
241 // ignore return and error - we're only want to check the parameter handling.
242 s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Id: "sg-67ad940e", Name: "ignored"}, perms)
243
244=== modified file 'ec2/ec2i_test.go'
245--- ec2/ec2i_test.go 2014-08-11 22:08:47 +0000
246+++ ec2/ec2i_test.go 2014-11-27 15:29:26 +0000
247@@ -4,10 +4,10 @@
248 "crypto/rand"
249 "fmt"
250
251+ . "gopkg.in/check.v1"
252 "launchpad.net/goamz/aws"
253 "launchpad.net/goamz/ec2"
254 "launchpad.net/goamz/testutil"
255- . "gopkg.in/check.v1"
256 )
257
258 // AmazonServer represents an Amazon EC2 server.
259@@ -108,13 +108,13 @@
260 s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
261 defer s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
262
263- resp1, err := s.ec2.CreateSecurityGroup(name, descr)
264+ resp1, err := s.ec2.CreateSecurityGroup("", name, descr)
265 c.Assert(err, IsNil)
266 c.Assert(resp1.RequestId, Matches, ".+")
267 c.Assert(resp1.Name, Equals, name)
268 c.Assert(resp1.Id, Matches, ".+")
269
270- resp1, err = s.ec2.CreateSecurityGroup(name, descr)
271+ resp1, err = s.ec2.CreateSecurityGroup("", name, descr)
272 ec2err, _ := err.(*ec2.Error)
273 c.Assert(resp1, IsNil)
274 c.Assert(ec2err, NotNil)
275@@ -124,7 +124,7 @@
276 Protocol: "tcp",
277 FromPort: 0,
278 ToPort: 1024,
279- SourceIPs: []string{"127.0.0.1/24"},
280+ SourceIPs: sourceIPs("127.0.0.0/24"),
281 }}
282
283 resp2, err := s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms)
284@@ -143,7 +143,7 @@
285 c.Assert(g0.IPPerms[0].Protocol, Equals, "tcp")
286 c.Assert(g0.IPPerms[0].FromPort, Equals, 0)
287 c.Assert(g0.IPPerms[0].ToPort, Equals, 1024)
288- c.Assert(g0.IPPerms[0].SourceIPs, DeepEquals, []string{"127.0.0.1/24"})
289+ c.Assert(g0.IPPerms[0].SourceIPs, DeepEquals, sourceIPs("127.0.0.0/24"))
290
291 resp2, err = s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
292 c.Assert(err, IsNil)
293@@ -178,7 +178,7 @@
294 Protocol: "tcp",
295 FromPort: 80,
296 ToPort: 80,
297- SourceIPs: []string{"127.0.0.1/32"},
298+ SourceIPs: sourceIPs("127.0.0.1/32"),
299 }}
300 errs := make(chan error, len(allRegions))
301 for _, region := range allRegions {
302
303=== modified file 'ec2/ec2t_test.go'
304--- ec2/ec2t_test.go 2014-08-11 22:08:47 +0000
305+++ ec2/ec2t_test.go 2014-11-27 15:29:26 +0000
306@@ -7,11 +7,11 @@
307 "sort"
308 "time"
309
310+ . "gopkg.in/check.v1"
311 "launchpad.net/goamz/aws"
312 "launchpad.net/goamz/ec2"
313 "launchpad.net/goamz/ec2/ec2test"
314 "launchpad.net/goamz/testutil"
315- . "gopkg.in/check.v1"
316 )
317
318 // LocalServer represents a local ec2test fake server.
319@@ -230,7 +230,18 @@
320 switch attr.Name {
321 case "supported-platforms":
322 sort.Strings(attr.Values)
323- c.Assert(attr.Values, DeepEquals, []string{"EC2", "VPC"})
324+ c.Assert(attr.Values, Not(HasLen), 0)
325+ if len(attr.Values) == 2 {
326+ c.Assert(attr.Values, DeepEquals, []string{"EC2", "VPC"})
327+ } else if len(attr.Values) == 1 {
328+ // Some regions have only VPC or EC2 enabled, and
329+ // because this test runs both against a local test
330+ // server and against the Amazon servers we need to
331+ // account for both cases.
332+ c.Assert(attr.Values[0], Matches, `(EC2|VPC)`)
333+ } else {
334+ c.Fatalf("unexpected account attributes: %v", attr.Values)
335+ }
336 case "default-vpc":
337 c.Assert(attr.Values, HasLen, 1)
338 c.Assert(attr.Values[0], Not(Equals), "")
339@@ -244,8 +255,8 @@
340 defaultVPCId, defaultSubnets := s.getDefaultVPCIdAndSubnets(c)
341 subnet := defaultSubnets[0]
342
343- g0 := s.makeTestGroupVPC(c, defaultVPCId, "goamz-test0", "ec2test group 0")
344- g1 := s.makeTestGroupVPC(c, defaultVPCId, "goamz-test1", "ec2test group 1")
345+ g0 := s.makeTestGroup(c, defaultVPCId, "goamz-test0", "ec2test group 0")
346+ g1 := s.makeTestGroup(c, defaultVPCId, "goamz-test1", "ec2test group 1")
347 defer s.deleteGroups(c, []ec2.SecurityGroup{g0, g1})
348
349 ip1 := validIPForSubnet(c, subnet, 5)
350@@ -345,7 +356,10 @@
351 // the instance might launch in any one.
352 for _, sub := range defaultSubnets {
353 if inst.SubnetId == sub.Id {
354- subnet = &sub
355+ subnet.Id = sub.Id
356+ subnet.VPCId = sub.VPCId
357+ subnet.CIDRBlock = sub.CIDRBlock
358+ break
359 }
360 }
361 }
362@@ -419,26 +433,23 @@
363 c.Fatalf("%v INSTANCES LEFT RUNNING!!!", ids)
364 }
365
366-func (s *ServerTests) makeTestGroup(c *C, name, descr string) ec2.SecurityGroup {
367- return s.makeTestGroupVPC(c, "", name, descr)
368-}
369-
370-func (s *ServerTests) makeTestGroupVPC(c *C, vpcId, name, descr string) ec2.SecurityGroup {
371+func (s *ServerTests) makeTestGroup(c *C, vpcId, name, descr string) ec2.SecurityGroup {
372 // Clean it up if a previous test left it around.
373 _, err := s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
374 if err != nil && errorCode(err) != "InvalidGroup.NotFound" {
375 c.Fatalf("delete security group: %v", err)
376 }
377
378- resp, err := s.ec2.CreateSecurityGroupVPC(vpcId, name, descr)
379+ resp, err := s.ec2.CreateSecurityGroup(vpcId, name, descr)
380 c.Assert(err, IsNil)
381- c.Assert(resp.Name, Equals, name)
382+ c.Assert(resp.Id, Matches, "sg-.+")
383+ c.Logf("created group %v", resp.SecurityGroup)
384 return resp.SecurityGroup
385 }
386
387 func (s *ServerTests) TestIPPerms(c *C) {
388- g0 := s.makeTestGroup(c, "goamz-test0", "ec2test group 0")
389- g1 := s.makeTestGroup(c, "goamz-test1", "ec2test group 1")
390+ g0 := s.makeTestGroup(c, "", "goamz-test0", "ec2test group 0")
391+ g1 := s.makeTestGroup(c, "", "goamz-test1", "ec2test group 1")
392 defer s.deleteGroups(c, []ec2.SecurityGroup{g0, g1})
393
394 resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{g0, g1}, nil)
395@@ -446,6 +457,10 @@
396 c.Assert(resp.Groups, HasLen, 2)
397 c.Assert(resp.Groups[0].IPPerms, HasLen, 0)
398 c.Assert(resp.Groups[1].IPPerms, HasLen, 0)
399+ nameRegexp := fmt.Sprintf("(%s|%s)", regexp.QuoteMeta(g0.Name), regexp.QuoteMeta(g1.Name))
400+ for _, rgroup := range resp.Groups {
401+ c.Check(rgroup.Name, Matches, nameRegexp)
402+ }
403
404 ownerId := resp.Groups[0].OwnerId
405
406@@ -455,17 +470,17 @@
407 Protocol: "tcp",
408 FromPort: 0,
409 ToPort: 1024,
410- SourceIPs: []string{"z127.0.0.1/24"},
411+ SourceIPs: sourceIPs("invalid"),
412 }})
413 c.Assert(err, NotNil)
414- c.Check(errorCode(err), Equals, "InvalidPermission.Malformed")
415+ c.Check(errorCode(err), Equals, "InvalidParameterValue")
416
417 // Check that AuthorizeSecurityGroup adds the correct authorizations.
418 _, err = s.ec2.AuthorizeSecurityGroup(g0, []ec2.IPPerm{{
419 Protocol: "tcp",
420 FromPort: 2000,
421 ToPort: 2001,
422- SourceIPs: []string{"127.0.0.0/24"},
423+ SourceIPs: sourceIPs("127.0.0.0/24"),
424 SourceGroups: []ec2.UserSecurityGroup{{
425 Name: g1.Name,
426 }, {
427@@ -475,48 +490,48 @@
428 Protocol: "tcp",
429 FromPort: 2000,
430 ToPort: 2001,
431- SourceIPs: []string{"200.1.1.34/32"},
432+ SourceIPs: sourceIPs("200.1.1.34/32"),
433 }})
434 c.Assert(err, IsNil)
435
436 resp, err = s.ec2.SecurityGroups([]ec2.SecurityGroup{g0}, nil)
437 c.Assert(err, IsNil)
438 c.Assert(resp.Groups, HasLen, 1)
439- c.Assert(resp.Groups[0].IPPerms, HasLen, 1)
440-
441- perm := resp.Groups[0].IPPerms[0]
442- srcg := perm.SourceGroups
443- c.Assert(srcg, HasLen, 2)
444-
445- // Normalize so we don't care about returned order.
446- if srcg[0].Name == g1.Name {
447- srcg[0], srcg[1] = srcg[1], srcg[0]
448+ c.Assert(resp.Groups[0].IPPerms, HasLen, 3)
449+
450+ for _, perm := range resp.Groups[0].IPPerms {
451+ srcg := perm.SourceGroups
452+ if len(srcg) == 0 {
453+ // Only SourceIPs should exist.
454+ c.Check(perm.SourceIPs, DeepEquals, sourceIPs("127.0.0.0/24", "200.1.1.34/32"))
455+ c.Check(srcg, HasLen, 0)
456+ } else {
457+ // Only SourceGroups should exist, and there should be one
458+ // group per IPPerm.
459+ c.Check(srcg, HasLen, 1)
460+ c.Check(perm.SourceIPs, HasLen, 0)
461+
462+ idRegexp := fmt.Sprintf("(%s|%s)", regexp.QuoteMeta(g0.Id), regexp.QuoteMeta(g1.Id))
463+ c.Check(srcg[0].Id, Matches, idRegexp)
464+ c.Check(srcg[0].OwnerId, Equals, ownerId)
465+ }
466 }
467- c.Check(srcg[0].Name, Equals, g0.Name)
468- c.Check(srcg[0].Id, Equals, g0.Id)
469- c.Check(srcg[0].OwnerId, Equals, ownerId)
470- c.Check(srcg[1].Name, Equals, g1.Name)
471- c.Check(srcg[1].Id, Equals, g1.Id)
472- c.Check(srcg[1].OwnerId, Equals, ownerId)
473-
474- sort.Strings(perm.SourceIPs)
475- c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24", "200.1.1.34/32"})
476
477 // Check that we can't delete g1 (because g0 is using it)
478 _, err = s.ec2.DeleteSecurityGroup(g1)
479 c.Assert(err, NotNil)
480- c.Check(errorCode(err), Equals, "InvalidGroup.InUse")
481+ c.Check(errorCode(err), Equals, "DependencyViolation")
482
483 _, err = s.ec2.RevokeSecurityGroup(g0, []ec2.IPPerm{{
484 Protocol: "tcp",
485 FromPort: 2000,
486 ToPort: 2001,
487- SourceGroups: []ec2.UserSecurityGroup{{Id: g1.Id}},
488+ SourceGroups: []ec2.UserSecurityGroup{{Id: g1.Id}, {Name: g0.Name}},
489 }, {
490 Protocol: "tcp",
491 FromPort: 2000,
492 ToPort: 2001,
493- SourceIPs: []string{"200.1.1.34/32"},
494+ SourceIPs: sourceIPs("200.1.1.34/32"),
495 }})
496 c.Assert(err, IsNil)
497
498@@ -525,14 +540,10 @@
499 c.Assert(resp.Groups, HasLen, 1)
500 c.Assert(resp.Groups[0].IPPerms, HasLen, 1)
501
502- perm = resp.Groups[0].IPPerms[0]
503- srcg = perm.SourceGroups
504- c.Assert(srcg, HasLen, 1)
505- c.Check(srcg[0].Name, Equals, g0.Name)
506- c.Check(srcg[0].Id, Equals, g0.Id)
507- c.Check(srcg[0].OwnerId, Equals, ownerId)
508+ perm := resp.Groups[0].IPPerms[0]
509+ c.Assert(perm.SourceGroups, HasLen, 0)
510
511- c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24"})
512+ c.Check(perm.SourceIPs, DeepEquals, sourceIPs("127.0.0.0/24"))
513
514 // We should be able to delete g1 now because we've removed its only use.
515 _, err = s.ec2.DeleteSecurityGroup(g1)
516@@ -556,7 +567,7 @@
517 s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
518 defer s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
519
520- resp1, err := s.ec2.CreateSecurityGroup(name, descr)
521+ resp1, err := s.ec2.CreateSecurityGroup("", name, descr)
522 c.Assert(err, IsNil)
523 c.Assert(resp1.Name, Equals, name)
524
525@@ -564,12 +575,12 @@
526 Protocol: "tcp",
527 FromPort: 200,
528 ToPort: 1024,
529- SourceIPs: []string{"127.0.0.1/24"},
530+ SourceIPs: sourceIPs("127.0.0.1/24"),
531 }, {
532 Protocol: "tcp",
533 FromPort: 0,
534 ToPort: 100,
535- SourceIPs: []string{"127.0.0.1/24"},
536+ SourceIPs: sourceIPs("127.0.0.1/24"),
537 }}
538
539 _, err = s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms[0:1])
540@@ -590,24 +601,34 @@
541 vpcId := vpcResp.VPC.Id
542 defer s.deleteVPCs(c, []string{vpcId})
543
544- subResp := s.createSubnet(c, vpcId, "10.4.1.0/24", "")
545+ // Set AZ to us-east-1c explicitly, as t1.micro is not supported
546+ // on us-east-1e, if it happens to get picked up randomly during
547+ // the live test.
548+ subResp := s.createSubnet(c, vpcId, "10.4.1.0/24", "us-east-1c")
549 subId := subResp.Subnet.Id
550 defer s.deleteSubnets(c, []string{subId})
551
552 groupResp, err := s.ec2.CreateSecurityGroup(
553+ "",
554 sessionName("testgroup1"),
555 "testgroup one description",
556 )
557 c.Assert(err, IsNil)
558 group1 := groupResp.SecurityGroup
559+ c.Assert(group1.Name, Not(Equals), "")
560+ c.Assert(group1.Id, Matches, "sg-.+")
561+ c.Logf("created group %v", group1)
562
563- groupResp, err = s.ec2.CreateSecurityGroupVPC(
564+ groupResp, err = s.ec2.CreateSecurityGroup(
565 vpcId,
566 sessionName("testgroup2"),
567 "testgroup two description vpc",
568 )
569 c.Assert(err, IsNil)
570 group2 := groupResp.SecurityGroup
571+ c.Assert(group2.Name, Not(Equals), "")
572+ c.Assert(group2.Id, Matches, "sg-.+")
573+ c.Logf("created group %v", group2)
574
575 defer s.deleteGroups(c, []ec2.SecurityGroup{group1, group2})
576
577@@ -679,24 +700,12 @@
578 {"instance-id", []string{"i-deadbeef12345"}},
579 },
580 }, {
581- about: "check that filtering on group id works",
582- filters: []filterSpec{
583- {"group-id", []string{group1.Id}},
584- },
585- resultIds: ids(0, 1),
586- }, {
587 about: "check that filtering on group id with instance prefix works",
588 filters: []filterSpec{
589 {"instance.group-id", []string{group1.Id}},
590 },
591 resultIds: ids(0, 1),
592 }, {
593- about: "check that filtering on group name works",
594- filters: []filterSpec{
595- {"group-name", []string{group1.Name}},
596- },
597- resultIds: ids(0, 1),
598- }, {
599 about: "check that filtering on group name with instance prefix works",
600 filters: []filterSpec{
601 {"instance.group-name", []string{group1.Name}},
602@@ -713,14 +722,14 @@
603 about: "combination filters 1",
604 filters: []filterSpec{
605 {"image-id", []string{imageId, imageId2}},
606- {"group-name", []string{group1.Name}},
607+ {"instance.group-name", []string{group1.Name}},
608 },
609 resultIds: ids(0, 1),
610 }, {
611 about: "combination filters 2",
612 filters: []filterSpec{
613 {"image-id", []string{imageId2}},
614- {"group-name", []string{group1.Name}},
615+ {"instance.group-name", []string{group1.Name}},
616 },
617 }, {
618 about: "VPC filters in combination",
619@@ -740,6 +749,8 @@
620 f.Add(spec.name, spec.values...)
621 }
622 }
623+ c.Logf("\tusing filter: %v", f)
624+ c.Logf("\texpecting result ids: %v", t.resultIds)
625 resp, err := s.ec2.Instances(t.instanceIds, f)
626 if t.err != "" {
627 c.Check(err, ErrorMatches, t.err)
628@@ -769,11 +780,14 @@
629 vpcId := vpcResp.VPC.Id
630 defer s.deleteVPCs(c, []string{vpcId})
631
632- subResp := s.createSubnet(c, vpcId, "10.6.1.0/24", "")
633+ // Set AZ to us-east-1c explicitly, as t1.micro is not supported
634+ // on us-east-1e, if it happens to get picked up randomly during
635+ // the live test.
636+ subResp := s.createSubnet(c, vpcId, "10.6.1.0/24", "us-east-1c")
637 subId := subResp.Subnet.Id
638 defer s.deleteSubnets(c, []string{subId})
639
640- groupResp, err := s.ec2.CreateSecurityGroupVPC(
641+ groupResp, err := s.ec2.CreateSecurityGroup(
642 vpcId,
643 sessionName("testgroup1 vpc"),
644 "testgroup description vpc",
645@@ -881,9 +895,9 @@
646 // Create the first one as a VPC group.
647 gid += " vpc"
648 desc += " vpc"
649- resp, err = s.ec2.CreateSecurityGroupVPC(vpcId, gid, desc)
650+ resp, err = s.ec2.CreateSecurityGroup(vpcId, gid, desc)
651 } else {
652- resp, err = s.ec2.CreateSecurityGroup(gid, desc)
653+ resp, err = s.ec2.CreateSecurityGroup("", gid, desc)
654 }
655 c.Assert(err, IsNil)
656 g[i] = resp.SecurityGroup
657@@ -900,7 +914,7 @@
658 Protocol: "tcp",
659 FromPort: 100,
660 ToPort: 200,
661- SourceIPs: []string{"1.2.3.4/32"},
662+ SourceIPs: sourceIPs("1.2.3.4/32"),
663 }},
664 {{
665 Protocol: "tcp",
666@@ -958,7 +972,7 @@
667 results: groups(1, 2),
668 }, {
669 about: "check that specifying a non-existent group id gives an error",
670- groups: append(groups(0), ec2.SecurityGroup{Id: "sg-eeeeeeeee"}),
671+ groups: append(groups(0), ec2.SecurityGroup{Id: "sg-eeeeeeee"}),
672 err: `.*\(InvalidGroup\.NotFound\)`,
673 }, {
674 about: "check that a filter allowed two groups returns both of them",
675@@ -977,13 +991,14 @@
676 }, {
677 about: "check that a filter allowing no groups returns none",
678 filters: []filterSpec{
679- {"group-id", []string{"sg-eeeeeeeee"}},
680+ {"group-id", []string{"sg-eeeeeeee"}},
681 },
682 },
683 filterCheck("description", "testdescription1", groups(1)),
684 filterCheck("group-name", g[2].Name, groups(2)),
685+ filterCheck("group-id", g[2].Id, groups(2)),
686 filterCheck("ip-permission.cidr", "1.2.3.4/32", groups(1)),
687- filterCheck("ip-permission.group-name", g[2].Name, groups(2, 3)),
688+ filterCheck("ip-permission.group-id", g[2].Id, groups(2, 3)),
689 filterCheck("ip-permission.protocol", "udp", groups(3)),
690 filterCheck("ip-permission.from-port", "200", groups(2, 3)),
691 filterCheck("ip-permission.to-port", "200", groups(1)),
692@@ -999,12 +1014,14 @@
693 f.Add(spec.name, spec.values...)
694 }
695 }
696+ c.Logf("\tusing filter: %v", f)
697+ c.Logf("\texpecting results: %v", t.results)
698 resp, err := s.ec2.SecurityGroups(t.groups, f)
699 if t.err != "" {
700 c.Check(err, ErrorMatches, t.err)
701 continue
702 }
703- c.Assert(err, IsNil)
704+ c.Check(err, IsNil)
705 groups := make(map[string]*ec2.SecurityGroup)
706 for j := range resp.Groups {
707 group := &resp.Groups[j].SecurityGroup
708@@ -1025,8 +1042,10 @@
709 c.Check(groups, HasLen, len(t.results))
710 for j, g := range t.results {
711 rg := groups[g.Id]
712- c.Assert(rg, NotNil, Commentf("group %d (%v) not found; got %#v", j, g, groups))
713- c.Check(rg.Name, Equals, g.Name, Commentf("group %d (%v)", j, g))
714+ c.Check(rg, NotNil, Commentf("group %d (%v) not found; got %#v", j, g, groups))
715+ if rg != nil {
716+ c.Check(rg.Name, Equals, g.Name, Commentf("group %d (%v)", j, g))
717+ }
718 }
719 }
720 }
721
722=== modified file 'ec2/ec2test/server.go'
723--- ec2/ec2test/server.go 2014-06-04 05:44:18 +0000
724+++ ec2/ec2test/server.go 2014-11-27 15:29:26 +0000
725@@ -141,6 +141,10 @@
726 return g.hasPerm(func(k permKey) bool {
727 return k.group != nil && k.group.name == value
728 }), nil
729+ case "ip-permission.group-id":
730+ return g.hasPerm(func(k permKey) bool {
731+ return k.group != nil && k.group.id == value
732+ }), nil
733 case "ip-permission.from-port":
734 port, err := strconv.Atoi(value)
735 if err != nil {
736@@ -176,13 +180,12 @@
737 // to g. It groups permissions by port range and protocol.
738 func (g *securityGroup) ec2Perms() (perms []ec2.IPPerm) {
739 // The grouping is held in result. We use permKey for convenience,
740- // (ensuring that the group and ipAddr of each key is zero). For
741- // each protocol/port range combination, we build up the permission
742- // set in the associated value.
743+ // (ensuring that the ipAddr of each key is zero). For each
744+ // protocol/port range combination, we build up the permission set
745+ // in the associated value.
746 result := make(map[permKey]*ec2.IPPerm)
747 for k := range g.perms {
748 groupKey := k
749- groupKey.group = nil
750 groupKey.ipAddr = ""
751
752 ec2p := result[groupKey]
753@@ -192,7 +195,6 @@
754 FromPort: k.fromPort,
755 ToPort: k.toPort,
756 }
757- result[groupKey] = ec2p
758 }
759 if k.group != nil {
760 ec2p.SourceGroups = append(ec2p.SourceGroups,
761@@ -202,9 +204,11 @@
762 OwnerId: ownerId,
763 })
764 } else {
765- ec2p.SourceIPs = append(ec2p.SourceIPs, k.ipAddr)
766+ ec2p.SourceIPs = append(ec2p.SourceIPs, ec2.CIDRIP{k.ipAddr})
767 }
768+ result[groupKey] = ec2p
769 }
770+
771 for _, ec2p := range result {
772 perms = append(perms, *ec2p)
773 }
774@@ -1313,7 +1317,7 @@
775 }
776
777 var (
778- secGroupPat = regexp.MustCompile(`^sg-[a-z0-9]+$`)
779+ secGroupPat = regexp.MustCompile(`^sg-[a-f0-9]+$`)
780 cidrIpPat = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/([0-9]+)$`)
781 ownerIdPat = regexp.MustCompile(`^[0-9]+$`)
782 )
783@@ -1401,9 +1405,9 @@
784 switch rest {
785 case "CidrIp":
786 if !cidrIpPat.MatchString(val) {
787- fatalf(400, "InvalidPermission.Malformed", "Invalid IP range: %q", val)
788+ fatalf(400, "InvalidParameterValue", "Invalid IP range: %q", val)
789 }
790- ec2p.SourceIPs = append(ec2p.SourceIPs, val)
791+ ec2p.SourceIPs = append(ec2p.SourceIPs, ec2.CIDRIP{val})
792 default:
793 fatalf(400, "UnknownParameter", "unknown parameter %q", name)
794 }
795@@ -1451,7 +1455,7 @@
796 }
797 k.group = nil
798 for _, ip := range p.SourceIPs {
799- k.ipAddr = ip
800+ k.ipAddr = ip.IP
801 result = append(result, k)
802 }
803 }
804@@ -1471,7 +1475,7 @@
805 for _, r := range srv.reservations {
806 for _, h := range r.groups {
807 if h == g && r.hasRunningMachine() {
808- fatalf(500, "InvalidGroup.InUse", "group is currently in use by a running instance")
809+ fatalf(500, "DependencyViolation", "group is currently in use by a running instance")
810 }
811 }
812 }
813@@ -1482,7 +1486,7 @@
814 }
815 for k := range sg.perms {
816 if k.group == g {
817- fatalf(500, "InvalidGroup.InUse", "group is currently in use by group %q", sg.id)
818+ fatalf(500, "DependencyViolation", "group is currently in use by group %q", sg.id)
819 }
820 }
821 }
822
823=== modified file 'ec2/export_test.go'
824--- ec2/export_test.go 2014-08-11 22:08:47 +0000
825+++ ec2/export_test.go 2014-11-27 15:29:26 +0000
826@@ -15,5 +15,3 @@
827 timeNow = time.Now
828 }
829 }
830-
831-var PrepareRunParams = prepareRunParams
832
833=== modified file 'ec2/networkinterfaces.go'
834--- ec2/networkinterfaces.go 2014-02-12 17:29:13 +0000
835+++ ec2/networkinterfaces.go 2014-11-27 15:29:26 +0000
836@@ -97,7 +97,7 @@
837 //
838 // See http://goo.gl/ze3VhA for more details.
839 func (ec2 *EC2) CreateNetworkInterface(opts CreateNetworkInterface) (resp *CreateNetworkInterfaceResp, err error) {
840- params := makeParamsVPC("CreateNetworkInterface")
841+ params := makeParams("CreateNetworkInterface")
842 params["SubnetId"] = opts.SubnetId
843 for i, ip := range opts.PrivateIPs {
844 prefix := fmt.Sprintf("PrivateIpAddresses.%d.", i+1)
845@@ -127,7 +127,7 @@
846 //
847 // See http://goo.gl/MC1yOj for more details.
848 func (ec2 *EC2) DeleteNetworkInterface(id string) (resp *SimpleResp, err error) {
849- params := makeParamsVPC("DeleteNetworkInterface")
850+ params := makeParams("DeleteNetworkInterface")
851 params["NetworkInterfaceId"] = id
852 resp = &SimpleResp{}
853 err = ec2.query(params, resp)
854@@ -153,7 +153,7 @@
855 //
856 // See http://goo.gl/2LcXtM for more details.
857 func (ec2 *EC2) NetworkInterfaces(ids []string, filter *Filter) (resp *NetworkInterfacesResp, err error) {
858- params := makeParamsVPC("DescribeNetworkInterfaces")
859+ params := makeParams("DescribeNetworkInterfaces")
860 for i, id := range ids {
861 params["NetworkInterfaceId."+strconv.Itoa(i+1)] = id
862 }
863@@ -180,7 +180,7 @@
864 //
865 // See http://goo.gl/rEbSii for more details.
866 func (ec2 *EC2) AttachNetworkInterface(interfaceId, instanceId string, deviceIndex int) (resp *AttachNetworkInterfaceResp, err error) {
867- params := makeParamsVPC("AttachNetworkInterface")
868+ params := makeParams("AttachNetworkInterface")
869 params["NetworkInterfaceId"] = interfaceId
870 params["InstanceId"] = instanceId
871 params["DeviceIndex"] = strconv.Itoa(deviceIndex)
872@@ -197,7 +197,7 @@
873 //
874 // See http://goo.gl/0Xc1px for more details.
875 func (ec2 *EC2) DetachNetworkInterface(attachmentId string, force bool) (resp *SimpleResp, err error) {
876- params := makeParamsVPC("DetachNetworkInterface")
877+ params := makeParams("DetachNetworkInterface")
878 params["AttachmentId"] = attachmentId
879 if force {
880 // Force is optional.
881
882=== modified file 'ec2/networkinterfaces_test.go'
883--- ec2/networkinterfaces_test.go 2014-08-11 22:08:47 +0000
884+++ ec2/networkinterfaces_test.go 2014-11-27 15:29:26 +0000
885@@ -9,10 +9,10 @@
886 package ec2_test
887
888 import (
889+ "time"
890+ . "gopkg.in/check.v1"
891 "launchpad.net/goamz/aws"
892 "launchpad.net/goamz/ec2"
893- . "gopkg.in/check.v1"
894- "time"
895 )
896
897 // Network interface tests with example responses
898@@ -196,11 +196,14 @@
899 vpcId := vpcResp.VPC.Id
900 defer s.deleteVPCs(c, []string{vpcId})
901
902- subResp := s.createSubnet(c, vpcId, "10.3.1.0/24", "")
903+ // Set AZ to us-east-1c explicitly, as t1.micro is not supported
904+ // on us-east-1e, if it happens to get picked up randomly during
905+ // the live test.
906+ subResp := s.createSubnet(c, vpcId, "10.3.1.0/24", "us-east-1c")
907 subId := subResp.Subnet.Id
908 defer s.deleteSubnets(c, []string{subId})
909
910- sg := s.makeTestGroupVPC(c, vpcId, "vpc-sg-1", "vpc test group1")
911+ sg := s.makeTestGroup(c, vpcId, "vpc-sg-1", "vpc test group1")
912 defer s.deleteGroups(c, []ec2.SecurityGroup{sg})
913
914 instList, err := s.ec2.RunInstances(&ec2.RunInstances{
915
916=== modified file 'ec2/privateips.go'
917--- ec2/privateips.go 2014-02-12 17:29:13 +0000
918+++ ec2/privateips.go 2014-11-27 15:29:26 +0000
919@@ -24,7 +24,7 @@
920 //
921 // See http://goo.gl/MoeH0L more details.
922 func (ec2 *EC2) AssignPrivateIPAddresses(interfaceId string, ipAddresses []string, secondaryIPCount int, allowReassignment bool) (resp *SimpleResp, err error) {
923- params := makeParamsVPC("AssignPrivateIpAddresses")
924+ params := makeParams("AssignPrivateIpAddresses")
925 params["NetworkInterfaceId"] = interfaceId
926 if secondaryIPCount > 0 {
927 params["SecondaryPrivateIpAddressCount"] = strconv.Itoa(secondaryIPCount)
928@@ -51,7 +51,7 @@
929 //
930 // See http://goo.gl/RjGZdB for more details.
931 func (ec2 *EC2) UnassignPrivateIPAddresses(interfaceId string, ipAddresses []string) (resp *SimpleResp, err error) {
932- params := makeParamsVPC("UnassignPrivateIpAddresses")
933+ params := makeParams("UnassignPrivateIpAddresses")
934 params["NetworkInterfaceId"] = interfaceId
935 for i, ip := range ipAddresses {
936 // PrivateIpAddress is zero indexed.
937
938=== modified file 'ec2/privateips_test.go'
939--- ec2/privateips_test.go 2014-08-11 22:08:47 +0000
940+++ ec2/privateips_test.go 2014-11-27 15:29:26 +0000
941@@ -12,9 +12,9 @@
942 "strings"
943 "time"
944
945+ . "gopkg.in/check.v1"
946 "launchpad.net/goamz/aws"
947 "launchpad.net/goamz/ec2"
948- . "gopkg.in/check.v1"
949 )
950
951 // Private IP tests with example responses
952@@ -59,7 +59,10 @@
953 vpcId := vpcResp.VPC.Id
954 defer s.deleteVPCs(c, []string{vpcId})
955
956- subResp := s.createSubnet(c, vpcId, "10.7.1.0/24", "")
957+ // Set AZ to us-east-1c explicitly, as m1.medium is not supported
958+ // on us-east-1e, if it happens to get picked up randomly during
959+ // the live test.
960+ subResp := s.createSubnet(c, vpcId, "10.7.1.0/24", "us-east-1c")
961 subId := subResp.Subnet.Id
962 defer s.deleteSubnets(c, []string{subId})
963
964
965=== modified file 'ec2/subnets.go'
966--- ec2/subnets.go 2014-02-12 13:54:15 +0000
967+++ ec2/subnets.go 2014-11-27 15:29:26 +0000
968@@ -51,7 +51,7 @@
969 //
970 // See http://goo.gl/wLPhfI for more details.
971 func (ec2 *EC2) CreateSubnet(vpcId, cidrBlock, availZone string) (resp *CreateSubnetResp, err error) {
972- params := makeParamsVPC("CreateSubnet")
973+ params := makeParams("CreateSubnet")
974 params["VpcId"] = vpcId
975 params["CidrBlock"] = cidrBlock
976 if availZone != "" {
977@@ -70,7 +70,7 @@
978 //
979 // See http://goo.gl/KmhcBM for more details.
980 func (ec2 *EC2) DeleteSubnet(id string) (resp *SimpleResp, err error) {
981- params := makeParamsVPC("DeleteSubnet")
982+ params := makeParams("DeleteSubnet")
983 params["SubnetId"] = id
984 resp = &SimpleResp{}
985 err = ec2.query(params, resp)
986@@ -94,7 +94,7 @@
987 //
988 // See http://goo.gl/NTKQVI for more details.
989 func (ec2 *EC2) Subnets(ids []string, filter *Filter) (resp *SubnetsResp, err error) {
990- params := makeParamsVPC("DescribeSubnets")
991+ params := makeParams("DescribeSubnets")
992 for i, id := range ids {
993 params["SubnetId."+strconv.Itoa(i+1)] = id
994 }
995
996=== modified file 'ec2/vpc.go'
997--- ec2/vpc.go 2014-02-12 13:42:33 +0000
998+++ ec2/vpc.go 2014-11-27 15:29:26 +0000
999@@ -44,7 +44,7 @@
1000 //
1001 // See http://goo.gl/nkwjvN for more details.
1002 func (ec2 *EC2) CreateVPC(CIDRBlock, instanceTenancy string) (resp *CreateVPCResp, err error) {
1003- params := makeParamsVPC("CreateVpc")
1004+ params := makeParams("CreateVpc")
1005 params["CidrBlock"] = CIDRBlock
1006 if instanceTenancy == "" {
1007 instanceTenancy = "default"
1008@@ -66,7 +66,7 @@
1009 //
1010 // See http://goo.gl/bcxtbf for more details.
1011 func (ec2 *EC2) DeleteVPC(id string) (resp *SimpleResp, err error) {
1012- params := makeParamsVPC("DeleteVpc")
1013+ params := makeParams("DeleteVpc")
1014 params["VpcId"] = id
1015 resp = &SimpleResp{}
1016 err = ec2.query(params, resp)
1017@@ -90,7 +90,7 @@
1018 //
1019 // See http://goo.gl/Y5kHqG for more details.
1020 func (ec2 *EC2) VPCs(ids []string, filter *Filter) (resp *VPCsResp, err error) {
1021- params := makeParamsVPC("DescribeVpcs")
1022+ params := makeParams("DescribeVpcs")
1023 for i, id := range ids {
1024 params["VpcId."+strconv.Itoa(i+1)] = id
1025 }

Subscribers

People subscribed via source and target branches