Merge lp:~dimitern/goamz/update-aws-api-version-to-latest into lp:goamz
- update-aws-api-version-to-latest
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Foord (community) | Approve | ||
Martin Packman (community) | Approve | ||
Review via email: mp+243057@code.launchpad.net |
Commit message
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:
- CreateSecurityG
- 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
Michael Foord (mfoord) wrote : | # |
So long as we can live the incompatible changes to the security groups api it looks fine.
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.
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.
Dimiter Naydenov (dimitern) wrote : | # |
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:
AssignPrivateIp
AttachNetworkIn
CreateNetworkIn
CreateSecurityGroup
CreateSubnet
CreateVpc
DeleteNetworkIn
DeleteSubnet
DeleteVpc
DescribeAccount
DescribeNetwork
DescribeSubnets
DescribeVpcs
DetachNetworkIn
UnassignPrivate
non-VPC calls with no changes in 2014-10-01 vs 2011-12-15:
AuthorizeSecuri
CreateSnapshot
CreateTags
DeleteSnapshot
DescribeAvailab
DescribeSecurit
DescribeSnapshots
RebootInstances
RevokeSecurityG
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:
nextToken (added - not supported or used by juju; for pagination of results)
RunInstances
request changes:
response changes: the same as for DescribeInstances, except for nextToken
DescribeImages
request - no changes
response changes:
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,...
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
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 | } |
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: