Merge lp:~julian-edwards/gwacl/deletedisk into lp:gwacl

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: 185
Merged at revision: 179
Proposed branch: lp:~julian-edwards/gwacl/deletedisk
Merge into: lp:gwacl
Diff against target: 971 lines (+150/-103)
10 files modified
deletedisk_test.go (+3/-3)
management_base.go (+63/-30)
management_base_test.go (+30/-28)
management_test.go (+2/-5)
poller.go (+2/-1)
poller_test.go (+3/-3)
x509dispatcher.go (+8/-11)
x509dispatcher_test.go (+15/-6)
x509session.go (+8/-8)
x509session_test.go (+16/-8)
To merge this branch: bzr merge lp:~julian-edwards/gwacl/deletedisk
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+174337@code.launchpad.net

Commit message

Ensures each api call specifies its own x-ms-version and add Azure url links to relevant docs for each api call

Description of the change

I was intending this to be a fix for the disk deletion problem (http://paste.ubuntu.com/5864779/) but it doesn't work. However this branch still sorts out a few things:

 1. Adds Azure url links to relevant docs for each api call
 2. Ensures each api call specifies its own x-ms-version. This is critical to prevent future cock ups and also because the deletedisk call requires a version other than the old base version.
 3. Adds extra test coverage that was missing which ensures x-ms-header is set for all the session op methods.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Well I tell a lie - disk deletion has worked, so this fixes that too.

However the example program is still not cleaning up the storage, that needs looking at still.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Good stuff. Consistent function documentation is lagniappe, but particularly appreciated. Sometimes a top comment for a function doesn't help understanding per se, but I still find that applying them inconsistently can frustrate the scanning of code. It's as if it makes my eyes recover from an exception rather than processing the text in a straight loop.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'deletedisk_test.go'
2--- deletedisk_test.go 2013-06-27 10:55:35 +0000
3+++ deletedisk_test.go 2013-07-12 05:06:27 +0000
4@@ -73,7 +73,7 @@
5 c.Assert(response, IsNil)
6 c.Assert(err, IsNil)
7 expectedURL := api.session.composeURL("services/disks/" + diskName)
8- checkOneRequest(c, recordedRequests, expectedURL, []byte{}, "DELETE")
9+ checkOneRequest(c, recordedRequests, expectedURL, "2012-08-01", nil, "DELETE")
10 }
11
12 func (suite *deleteDiskSuite) TestManagementAPIDeleteDiskPolls(c *C) {
13@@ -98,6 +98,6 @@
14 c.Assert(err, IsNil)
15 expectedURL := api.session.composeURL("services/disks/" + diskName)
16 c.Check(len(recordedRequests), Equals, 2)
17- checkRequest(c, recordedRequests[0], expectedURL, []byte{}, "DELETE")
18- checkRequest(c, recordedRequests[1], expectedURL, []byte{}, "DELETE")
19+ checkRequest(c, recordedRequests[0], expectedURL, "2012-08-01", nil, "DELETE")
20+ checkRequest(c, recordedRequests[1], expectedURL, "2012-08-01", nil, "DELETE")
21 }
22
23=== modified file 'management_base.go'
24--- management_base.go 2013-07-10 15:42:42 +0000
25+++ management_base.go 2013-07-12 05:06:27 +0000
26@@ -97,7 +97,7 @@
27 // Images are returned in the order in which Azure lists them.
28 // http://msdn.microsoft.com/en-us/library/windowsazure/jj157191.aspx
29 func (api *ManagementAPI) ListOSImages() (*Images, error) {
30- response, err := api.session.get("services/images")
31+ response, err := api.session.get("services/images", "2013-03-01")
32 if err != nil {
33 return nil, err
34 }
35@@ -110,9 +110,9 @@
36 // Azure management API.
37 // HostedServiceDescriptor objects contains a small subset of the fields present in
38 // HostedService objects.
39+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460781.aspx
40 func (api *ManagementAPI) ListHostedServices() ([]HostedServiceDescriptor, error) {
41- URI := "services/hostedservices"
42- res, err := api.session.get(URI)
43+ res, err := api.session.get("services/hostedservices", "2012-03-01")
44 if err != nil {
45 return nil, err
46 }
47@@ -123,6 +123,7 @@
48
49 // UpdateHostedService updates the provided values on the named service.
50 // Use NewUpdateHostedService() to create an UpdateHostedService params object.
51+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg441303.aspx
52 func (api *ManagementAPI) UpdateHostedService(serviceName string, params *UpdateHostedService) error {
53 var err error
54 checkPathComponents(serviceName)
55@@ -131,7 +132,7 @@
56 if err != nil {
57 return err
58 }
59- response, err := api.session.put(URI, []byte(body), "application/xml")
60+ response, err := api.session.put(URI, "2012-03-01", []byte(body), "application/xml")
61 if err != nil {
62 return err
63 }
64@@ -140,6 +141,7 @@
65
66 // GetHostedServiceProperties loads a HostedService object from the Azure
67 // management API.
68+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460806.aspx
69 func (api *ManagementAPI) GetHostedServiceProperties(
70 serviceName string, embedDetail bool) (*HostedService, error) {
71 checkPathComponents(serviceName)
72@@ -150,7 +152,7 @@
73 case false:
74 URI += "false"
75 }
76- res, err := api.session.get(URI)
77+ res, err := api.session.get(URI, "2012-03-01")
78 if err != nil {
79 return nil, err
80 }
81@@ -162,21 +164,25 @@
82 // AddHostedService adds a hosted service.
83 // This is an asynchronous operation on Azure, but this call blocks until the
84 // operation is completed.
85+// This is actually called CreateHostedService in the Azure documentation.
86+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg441304.aspx
87 func (api *ManagementAPI) AddHostedService(definition *CreateHostedService) error {
88 URI := "services/hostedservices"
89 body, err := marshalXML(definition)
90 if err != nil {
91 return err
92 }
93- response, err := api.session.post(URI, []byte(body), "application/xml")
94+ response, err := api.session.post(URI, "2012-03-01", []byte(body), "application/xml")
95 if err != nil {
96 return err
97 }
98 return api.blockUntilCompleted(response)
99 }
100
101+// DeleteHostedService deletes the named hosted service.
102+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg441305.aspx
103 func (api *ManagementAPI) DeleteHostedService(serviceName string) error {
104- response, err := api.session.delete("services/hostedservices/" + serviceName)
105+ response, err := api.session.delete("services/hostedservices/" + serviceName, "2010-10-28")
106 if err != nil {
107 return err
108 }
109@@ -184,7 +190,10 @@
110 }
111
112 // AddDeployment adds a virtual machine deployment.
113-// This is an asynchronous operation, it blocks until the operation is completed.
114+// This is an asynchronous operation on Azure, but this call blocks until the
115+// operation is completed.
116+// This is actually called CreateDeployment in the Azure documentation.
117+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460813.aspx
118 func (api *ManagementAPI) AddDeployment(definition *Deployment, serviceName string) error {
119 checkPathComponents(serviceName)
120 URI := "services/hostedservices/" + serviceName + "/deployments"
121@@ -192,16 +201,18 @@
122 if err != nil {
123 return err
124 }
125- response, err := api.session.post(URI, []byte(body), "application/xml")
126+ response, err := api.session.post(URI, "2012-03-01", []byte(body), "application/xml")
127 if err != nil {
128 return err
129 }
130 return api.blockUntilCompleted(response)
131 }
132
133+// DeleteDeployment deletes the named deployment from the named hosted service.
134+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460815.aspx
135 func (api *ManagementAPI) DeleteDeployment(serviceName string, deploymentName string) error {
136 path := "services/hostedservices/" + serviceName + "/deployments/" + deploymentName
137- response, err := api.session.delete(path)
138+ response, err := api.session.delete(path, "2012-03-01")
139 if err != nil {
140 return err
141 }
142@@ -213,11 +224,14 @@
143 DeploymentName string
144 }
145
146+// GetDeployment returns a Deployment object for the named hosted service and
147+// deployment name.
148+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460804.aspx
149 func (api *ManagementAPI) GetDeployment(request *GetDeploymentRequest) (*Deployment, error) {
150 checkPathComponents(request.ServiceName)
151 checkPathComponents(request.DeploymentName)
152 path := "services/hostedservices/" + request.ServiceName + "/deployments/" + request.DeploymentName
153- response, err := api.session.get(path)
154+ response, err := api.session.get(path, "2012-03-01")
155 if err != nil {
156 return nil, err
157 }
158@@ -232,14 +246,17 @@
159 // AddStorageAccount starts the creation of a storage account. This is
160 // called a storage service in the Azure API, but nomenclature seems to
161 // have changed.
162-// This is an asynchronous operation, it blocks until the operation is completed.
163+// This is an asynchronous operation on Azure, but the call blocks until the
164+// operation is completed.
165+// This is actually called CreateStorageAccount in the Azure documentation.
166+// See http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx
167 func (api *ManagementAPI) AddStorageAccount(definition *CreateStorageServiceInput) error {
168 uri := "services/storageservices"
169 body, err := marshalXML(definition)
170 if err != nil {
171 return err
172 }
173- response, err := api.session.post(uri, []byte(body), "application/xml")
174+ response, err := api.session.post(uri, "2012-03-01", []byte(body), "application/xml")
175 if err != nil {
176 return err
177 }
178@@ -247,8 +264,9 @@
179 }
180
181 // DeleteStorageAccount deletes a storage account.
182+// See http://msdn.microsoft.com/en-us/library/windowsazure/hh264517.aspx
183 func (api *ManagementAPI) DeleteStorageAccount(storageAccountName string) error {
184- response, err := api.session.delete("services/storageservices/" + storageAccountName)
185+ response, err := api.session.delete("services/storageservices/" + storageAccountName, "2011-06-01")
186 if err != nil {
187 return err
188 }
189@@ -257,9 +275,10 @@
190
191 // GetStorageAccountKeys retrieves a storage account's primary and secondary
192 // access keys from the Azure service.
193+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460785.aspx
194 func (api *ManagementAPI) GetStorageAccountKeys(accountName string) (*StorageAccountKeys, error) {
195 url := "services/storageservices/" + accountName + "/keys"
196- res, err := api.session.get(url)
197+ res, err := api.session.get(url, "2009-10-01")
198 if err != nil {
199 return nil, err
200 }
201@@ -271,6 +290,9 @@
202 return &keys, nil
203 }
204
205+// DeleteDisk deletes the named OS/data disk.
206+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157200.aspx
207+// TODO: set comp=media to optionally delete associated blob.
208 func (api *ManagementAPI) DeleteDisk(diskName string) error {
209 // Use the disk deletion poller to work around a bug in Windows Azure.
210 // See the documentation in the file deletedisk.go for details.
211@@ -280,24 +302,25 @@
212 }
213
214 func (api *ManagementAPI) _DeleteDisk(diskName string) error {
215- response, err := api.session.delete("services/disks/" + diskName)
216+ response, err := api.session.delete(
217+ "services/disks/" + diskName, "2012-08-01")
218 if err != nil {
219 return err
220 }
221 return api.blockUntilCompleted(response)
222 }
223
224-// Perform an operation on the specified role (as defined by serviceName, deploymentName and
225-// roleName)
226-// This is an asynchronous operation, it blocks until the operation is completed.
227-func (api *ManagementAPI) performRoleOperation(serviceName string, deploymentName string, roleName string, operation *RoleOperation) error {
228+// Perform an operation on the specified role (as defined by serviceName,
229+// deploymentName and roleName) This is an asynchronous operation on Azure, but
230+// the call blocks until the operation is completed.
231+func (api *ManagementAPI) performRoleOperation(serviceName, deploymentName, roleName, apiVersion string, operation *RoleOperation) error {
232 checkPathComponents(serviceName, deploymentName, roleName)
233 URI := "services/hostedservices/" + serviceName + "/deployments/" + deploymentName + "/roleinstances/" + roleName + "/Operations"
234 body, err := marshalXML(operation)
235 if err != nil {
236 return err
237 }
238- response, err := api.session.post(URI, []byte(body), "application/xml")
239+ response, err := api.session.post(URI, apiVersion, []byte(body), "application/xml")
240 if err != nil {
241 return err
242 }
243@@ -313,40 +336,44 @@
244 type StartRoleRequest performRoleOperationRequest
245
246 // StartRole starts the named Role.
247+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157189.aspx
248 func (api *ManagementAPI) StartRole(request *StartRoleRequest) error {
249 return api.performRoleOperation(
250 request.ServiceName, request.DeploymentName, request.RoleName,
251- startRoleOperation)
252+ "2012-03-01", startRoleOperation)
253 }
254
255 type RestartRoleRequest performRoleOperationRequest
256
257 // RestartRole restarts the named Role.
258+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157197.aspx
259 func (api *ManagementAPI) RestartRole(request *RestartRoleRequest) error {
260 return api.performRoleOperation(
261 request.ServiceName, request.DeploymentName, request.RoleName,
262- restartRoleOperation)
263+ "2012-03-01", restartRoleOperation)
264 }
265
266 type ShutdownRoleRequest performRoleOperationRequest
267
268 // ShutdownRole shuts down the named Role.
269+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157195.aspx
270 func (api *ManagementAPI) ShutdownRole(request *ShutdownRoleRequest) error {
271 return api.performRoleOperation(
272 request.ServiceName, request.DeploymentName, request.RoleName,
273- shutdownRoleOperation)
274+ "2012-03-01", shutdownRoleOperation)
275 }
276
277 type GetRoleRequest performRoleOperationRequest
278
279 // GetRole requests the role data for the specified role.
280+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157193.aspx
281 func (api *ManagementAPI) GetRole(request *GetRoleRequest) (*GetRole, error) {
282 checkPathComponents(
283 request.ServiceName, request.DeploymentName, request.RoleName)
284 url := ("services/hostedservices/" + request.ServiceName +
285 "/deployments/" + request.DeploymentName + "/roles/" +
286 request.RoleName)
287- response, err := api.session.get(url)
288+ response, err := api.session.get(url, "2012-03-01")
289 if err != nil {
290 return nil, err
291 }
292@@ -363,6 +390,7 @@
293 }
294
295 // CreateAffinityGroup sends a request to make a new affinity group.
296+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg715317.aspx
297 func (api *ManagementAPI) CreateAffinityGroup(request *CreateAffinityGroupRequest) error {
298 var err error
299 url := "affinitygroups"
300@@ -370,7 +398,7 @@
301 if err != nil {
302 return err
303 }
304- response, err := api.session.post(url, []byte(body), "application/xml")
305+ response, err := api.session.post(url, "2012-03-01", []byte(body), "application/xml")
306 return api.blockUntilCompleted(response)
307 }
308
309@@ -380,6 +408,7 @@
310 }
311
312 // UpdateAffinityGroup sends a request to update the named affinity group.
313+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg715316.aspx
314 func (api *ManagementAPI) UpdateAffinityGroup(request *UpdateAffinityGroupRequest) error {
315 var err error
316 checkPathComponents(request.Name)
317@@ -388,7 +417,7 @@
318 if err != nil {
319 return err
320 }
321- response, err := api.session.put(url, []byte(body), "application/xml")
322+ response, err := api.session.put(url, "2011-02-25", []byte(body), "application/xml")
323 if err != nil {
324 return err
325 }
326@@ -400,6 +429,7 @@
327 }
328
329 // DeleteAffinityGroup requests a deletion of the named affinity group.
330+// See http://msdn.microsoft.com/en-us/library/windowsazure/gg715314.aspx
331 func (api *ManagementAPI) DeleteAffinityGroup(request *DeleteAffinityGroupRequest) error {
332 var err error
333 checkPathComponents(request.Name)
334@@ -407,7 +437,7 @@
335 if err != nil {
336 return err
337 }
338- response, err := api.session.delete(url)
339+ response, err := api.session.delete(url, "2011-02-25")
340 if err != nil {
341 return err
342 }
343@@ -417,8 +447,9 @@
344 // GetNetworkConfiguration gets the network configuration for this
345 // subscription. If there is no network configuration the configuration will
346 // be nil.
347+// See http://msdn.microsoft.com/en-us/library/windowsazure/jj157196.aspx
348 func (api *ManagementAPI) GetNetworkConfiguration() (*NetworkConfiguration, error) {
349- response, err := api.session.get("services/networking/media")
350+ response, err := api.session.get("services/networking/media", "2012-03-01")
351 if err != nil {
352 if IsNotFoundError(err) {
353 return nil, nil
354@@ -442,7 +473,9 @@
355 if err != nil {
356 return err
357 }
358- response, err := api.session.put("services/networking/media", []byte(body), "application/octet-stream")
359+ response, err := api.session.put(
360+ "services/networking/media", "2012-03-01", []byte(body),
361+ "application/octet-stream")
362 if err != nil {
363 return err
364 }
365
366=== modified file 'management_base_test.go'
367--- management_base_test.go 2013-07-10 16:02:17 +0000
368+++ management_base_test.go 2013-07-12 05:06:27 +0000
369@@ -246,17 +246,18 @@
370
371 // checkOneRequest asserts that the given slice contains one request, with the
372 // given characteristics.
373-func checkOneRequest(c *C, recordedRequests *[]*X509Request, URL string, payload []byte, Method string) {
374+func checkOneRequest(c *C, recordedRequests *[]*X509Request, URL, version string, payload []byte, Method string) {
375 requests := *recordedRequests
376 c.Assert(len(requests), Equals, 1)
377 request := requests[0]
378- checkRequest(c, request, URL, payload, Method)
379+ checkRequest(c, request, URL, version, payload, Method)
380 }
381
382-func checkRequest(c *C, request *X509Request, URL string, payload []byte, Method string) {
383- c.Assert(request.URL, Equals, URL)
384- c.Assert(string(request.Payload), Equals, string(payload))
385- c.Assert(request.Method, Equals, Method)
386+func checkRequest(c *C, request *X509Request, URL, version string, payload []byte, Method string) {
387+ c.Check(request.URL, Equals, URL)
388+ c.Check(string(request.Payload), Equals, string(payload))
389+ c.Check(request.Method, Equals, Method)
390+ c.Check(request.APIVersion, Equals, version)
391 }
392
393 func (suite *managementBaseAPISuite) TestGetOperationFailsIfNoHeader(c *C) {
394@@ -366,7 +367,7 @@
395
396 c.Assert(err, IsNil)
397 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices"
398- checkOneRequest(c, &recordedRequests, expectedURL, nil, "GET")
399+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", nil, "GET")
400 c.Assert(descriptors[0].URL, Equals, url)
401 }
402
403@@ -396,7 +397,7 @@
404
405 c.Assert(err, IsNil)
406 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices/" + serviceName
407- checkOneRequest(c, &recordedRequests, expectedURL, requestPayload, "PUT")
408+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", requestPayload, "PUT")
409 }
410
411 func assertGetHostedServicePropertiesRequest(c *C, api *ManagementAPI, serviceName string, embedDetail bool, httpRequest *X509Request) {
412@@ -408,7 +409,7 @@
413 }
414 expectedURL := fmt.Sprintf("%s%s/services/hostedservices/%s?%s", AZURE_URL,
415 api.session.subscriptionId, serviceName, query)
416- checkRequest(c, httpRequest, expectedURL, nil, "GET")
417+ checkRequest(c, httpRequest, expectedURL, "2012-03-01", nil, "GET")
418 }
419
420 func (suite *managementBaseAPISuite) TestGetHostedServiceProperties_withoutDetails(c *C) {
421@@ -517,13 +518,13 @@
422 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices"
423 expectedPayload, err := marshalXML(createHostedService)
424 c.Assert(err, IsNil)
425- checkOneRequest(c, recordedRequests, expectedURL, expectedPayload, "POST")
426+ checkOneRequest(c, recordedRequests, expectedURL, "2012-03-01", expectedPayload, "POST")
427 }
428
429 func assertDeleteHostedServiceRequest(c *C, api *ManagementAPI, serviceName string, httpRequest *X509Request) {
430 expectedURL := fmt.Sprintf("%s%s/services/hostedservices/%s", AZURE_URL,
431 api.session.subscriptionId, serviceName)
432- checkRequest(c, httpRequest, expectedURL, nil, "DELETE")
433+ checkRequest(c, httpRequest, expectedURL, "2010-10-28", nil, "DELETE")
434 }
435
436 func (suite *managementBaseAPISuite) TestDeleteHostedService(c *C) {
437@@ -550,14 +551,14 @@
438 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices/" + serviceName + "/deployments"
439 expectedPayload, err := marshalXML(deployment)
440 c.Assert(err, IsNil)
441- checkOneRequest(c, recordedRequests, expectedURL, expectedPayload, "POST")
442+ checkOneRequest(c, recordedRequests, expectedURL, "2012-03-01", expectedPayload, "POST")
443 }
444
445 func assertDeleteDeploymentRequest(c *C, api *ManagementAPI, hostedServiceName, deploymentName string, httpRequest *X509Request) {
446 expectedURL := fmt.Sprintf(
447 "%s%s/services/hostedservices/%s/deployments/%s", AZURE_URL,
448 api.session.subscriptionId, hostedServiceName, deploymentName)
449- checkRequest(c, httpRequest, expectedURL, nil, "DELETE")
450+ checkRequest(c, httpRequest, expectedURL, "2012-03-01", nil, "DELETE")
451 }
452
453 func (suite *managementBaseAPISuite) TestDeleteDeployment(c *C) {
454@@ -650,7 +651,7 @@
455 expectedURL := fmt.Sprintf(
456 "%s%s/services/hostedservices/%s/deployments/%s", AZURE_URL,
457 api.session.subscriptionId, request.ServiceName, request.DeploymentName)
458- checkRequest(c, httpRequest, expectedURL, nil, "GET")
459+ checkRequest(c, httpRequest, expectedURL, "2012-03-01", nil, "GET")
460 }
461
462 func (suite *managementBaseAPISuite) TestGetDeployment(c *C) {
463@@ -693,7 +694,7 @@
464 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/storageservices"
465 expectedPayload, err := marshalXML(cssi)
466 c.Assert(err, IsNil)
467- checkOneRequest(c, &recordedRequests, expectedURL, expectedPayload, "POST")
468+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", expectedPayload, "POST")
469 }
470
471 func (suite *managementBaseAPISuite) TestDeleteStorageAccount(c *C) {
472@@ -705,7 +706,7 @@
473 err := api.DeleteStorageAccount(accountName)
474 c.Assert(err, IsNil)
475
476- checkOneRequest(c, recordedRequests, accountURL, nil, "DELETE")
477+ checkOneRequest(c, recordedRequests, accountURL, "2011-06-01", nil, "DELETE")
478 }
479
480 func (suite *managementBaseAPISuite) TestGetStorageAccountKeys(c *C) {
481@@ -741,7 +742,7 @@
482 func assertDeleteDiskRequest(c *C, api *ManagementAPI, diskName string, httpRequest *X509Request) {
483 expectedURL := fmt.Sprintf("%s%s/services/disks/%s", AZURE_URL,
484 api.session.subscriptionId, diskName)
485- checkRequest(c, httpRequest, expectedURL, nil, "DELETE")
486+ checkRequest(c, httpRequest, expectedURL, "2012-08-01", nil, "DELETE")
487 }
488
489 func (suite *managementBaseAPISuite) TestDeleteDisk(c *C) {
490@@ -767,13 +768,14 @@
491 deploymentName := "deploymentName"
492 roleName := "roleName"
493 operation := newRoleOperation("RandomOperation")
494- err := api.performRoleOperation(serviceName, deploymentName, roleName, operation)
495+ version := "test-version"
496+ err := api.performRoleOperation(serviceName, deploymentName, roleName, version, operation)
497
498 c.Assert(err, IsNil)
499 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices/" + serviceName + "/deployments/" + deploymentName + "/roleinstances/" + roleName + "/Operations"
500 expectedPayload, err := marshalXML(operation)
501 c.Assert(err, IsNil)
502- checkOneRequest(c, recordedRequests, expectedURL, expectedPayload, "POST")
503+ checkOneRequest(c, recordedRequests, expectedURL, version, expectedPayload, "POST")
504 }
505
506 func (suite *managementBaseAPISuite) TestStartRole(c *C) {
507@@ -787,7 +789,7 @@
508 request.RoleName + "/Operations")
509 expectedPayload, err := marshalXML(startRoleOperation)
510 c.Assert(err, IsNil)
511- checkOneRequest(c, recordedRequests, expectedURL, expectedPayload, "POST")
512+ checkOneRequest(c, recordedRequests, expectedURL, "2012-03-01", expectedPayload, "POST")
513 }
514
515 func (suite *managementBaseAPISuite) TestRestartRole(c *C) {
516@@ -801,7 +803,7 @@
517 request.RoleName + "/Operations")
518 expectedPayload, err := marshalXML(restartRoleOperation)
519 c.Assert(err, IsNil)
520- checkOneRequest(c, recordedRequests, expectedURL, expectedPayload, "POST")
521+ checkOneRequest(c, recordedRequests, expectedURL, "2012-03-01", expectedPayload, "POST")
522 }
523
524 func assertShutdownRoleRequest(c *C, api *ManagementAPI, request *ShutdownRoleRequest, httpRequest *X509Request) {
525@@ -811,7 +813,7 @@
526 request.DeploymentName, request.RoleName)
527 expectedPayload, err := marshalXML(shutdownRoleOperation)
528 c.Assert(err, IsNil)
529- checkRequest(c, httpRequest, expectedURL, expectedPayload, "POST")
530+ checkRequest(c, httpRequest, expectedURL, "2012-03-01", expectedPayload, "POST")
531 }
532
533 func (suite *managementBaseAPISuite) TestShutdownRole(c *C) {
534@@ -843,7 +845,7 @@
535 "/services/hostedservices/" +
536 request.ServiceName + "/deployments/" + request.DeploymentName +
537 "/roles/" + request.RoleName)
538- checkOneRequest(c, &recordedRequests, expectedURL, nil, "GET")
539+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", nil, "GET")
540
541 c.Check(role.RoleName, Equals, "rolename")
542 }
543@@ -865,7 +867,7 @@
544
545 expectedURL := AZURE_URL + api.session.subscriptionId + "/affinitygroups"
546 expectedBody, _ := cag.Serialize()
547- checkOneRequest(c, &recordedRequests, expectedURL, []byte(expectedBody), "POST")
548+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", []byte(expectedBody), "POST")
549 }
550
551 func (suite *managementBaseAPISuite) TestUpdateAffinityGroup(c *C) {
552@@ -886,7 +888,7 @@
553 expectedURL := (AZURE_URL + api.session.subscriptionId +
554 "/affinitygroups/" + request.Name)
555 expectedBody, _ := uag.Serialize()
556- checkOneRequest(c, &recordedRequests, expectedURL, []byte(expectedBody), "PUT")
557+ checkOneRequest(c, &recordedRequests, expectedURL, "2011-02-25", []byte(expectedBody), "PUT")
558 }
559
560 func (suite *managementBaseAPISuite) TestDeleteAffinityGroup(c *C) {
561@@ -904,7 +906,7 @@
562
563 expectedURL := (AZURE_URL + api.session.subscriptionId +
564 "/affinitygroups/" + request.Name)
565- checkOneRequest(c, &recordedRequests, expectedURL, nil, "DELETE")
566+ checkOneRequest(c, &recordedRequests, expectedURL, "2011-02-25", nil, "DELETE")
567 }
568
569 func makeNetworkConfiguration() *NetworkConfiguration {
570@@ -964,7 +966,7 @@
571 expectedURL := fmt.Sprintf(
572 "%s%s/services/networking/media", AZURE_URL,
573 api.session.subscriptionId)
574- checkRequest(c, httpRequest, expectedURL, nil, "GET")
575+ checkRequest(c, httpRequest, expectedURL, "2012-03-01", nil, "GET")
576 }
577
578 func (suite *managementBaseAPISuite) TestGetNetworkConfiguration(c *C) {
579@@ -1014,5 +1016,5 @@
580
581 c.Assert(err, IsNil)
582 expectedURL := AZURE_URL + api.session.subscriptionId + "/services/networking/media"
583- checkOneRequest(c, &recordedRequests, expectedURL, requestPayload, "PUT")
584+ checkOneRequest(c, &recordedRequests, expectedURL, "2012-03-01", requestPayload, "PUT")
585 }
586
587=== modified file 'management_test.go'
588--- management_test.go 2013-07-10 15:37:52 +0000
589+++ management_test.go 2013-07-12 05:06:27 +0000
590@@ -88,11 +88,8 @@
591 expectedURL := fmt.Sprintf(
592 "%ssubscriptionId/services/hostedservices/%s?embed-detail=true",
593 AZURE_URL, service.ServiceName)
594- c.Check(record[0], DeepEquals, &X509Request{
595- APIVersion: baseAPIVersion,
596- URL: expectedURL,
597- Method: "GET",
598- })
599+ c.Check(record[0].URL, Equals, expectedURL)
600+ c.Check(record[0].Method, Equals, "GET")
601 }
602
603 func (suite *managementAPISuite) TestListInstancesFailsGettingDetails(c *C) {
604
605=== modified file 'poller.go'
606--- poller.go 2013-07-02 14:22:42 +0000
607+++ poller.go 2013-07-12 05:06:27 +0000
608@@ -93,9 +93,10 @@
609
610 // Poll issues a blocking request to microsoft Azure to fetch the information
611 // related to the operation associated with the poller.
612+// See http://msdn.microsoft.com/en-us/library/windowsazure/ee460783.aspx
613 func (poller operationPoller) poll() (*x509Response, error) {
614 URI := "operations/" + poller.operationID
615- return poller.api.session.get(URI)
616+ return poller.api.session.get(URI, "2009-10-01")
617 }
618
619 // IsDone returns true if the given response has a status code indicating
620
621=== modified file 'poller_test.go'
622--- poller_test.go 2013-07-02 13:51:00 +0000
623+++ poller_test.go 2013-07-12 05:06:27 +0000
624@@ -120,7 +120,7 @@
625
626 c.Assert(err, IsNil)
627 expectedURL := AZURE_URL + api.session.subscriptionId + "/operations/" + operationID
628- checkOneRequest(c, recordedRequests, expectedURL, []byte{}, "GET")
629+ checkOneRequest(c, recordedRequests, expectedURL, "2009-10-01", nil, "GET")
630 }
631
632 var operationXMLTemplate = dedent.Dedent(`
633@@ -212,6 +212,6 @@
634 operationPollerInstance := poller.(operationPoller)
635 expectedURL := AZURE_URL + operationPollerInstance.api.session.subscriptionId + "/operations/" + operationID
636 c.Assert(len(recordedRequests), Equals, 2)
637- checkRequest(c, recordedRequests[0], expectedURL, []byte{}, "GET")
638- checkRequest(c, recordedRequests[1], expectedURL, []byte{}, "GET")
639+ checkRequest(c, recordedRequests[0], expectedURL, "2009-10-01", nil, "GET")
640+ checkRequest(c, recordedRequests[1], expectedURL, "2009-10-01", nil, "GET")
641 }
642
643=== modified file 'x509dispatcher.go'
644--- x509dispatcher.go 2013-07-10 15:42:42 +0000
645+++ x509dispatcher.go 2013-07-12 05:06:27 +0000
646@@ -25,47 +25,44 @@
647 verbose = newVerbose
648 }
649
650-// baseAPIVersion is the default Azure API version to use.
651-const baseAPIVersion = "2013-03-01"
652-
653 // newX509RequestGET initializes an X509Request for a GET. You may still need
654 // to set further values.
655-func newX509RequestGET(url string) *X509Request {
656+func newX509RequestGET(url, apiVersion string) *X509Request {
657 return &X509Request{
658 Method: "GET",
659 URL: url,
660- APIVersion: baseAPIVersion,
661+ APIVersion: apiVersion,
662 }
663 }
664
665 // newX509RequestPOST initializes an X509Request for a POST. You may still
666 // need to set further values.
667-func newX509RequestPOST(url string, payload []byte, contentType string) *X509Request {
668+func newX509RequestPOST(url, apiVersion string, payload []byte, contentType string) *X509Request {
669 return &X509Request{
670 Method: "POST",
671 URL: url,
672- APIVersion: baseAPIVersion,
673+ APIVersion: apiVersion,
674 Payload: payload,
675 ContentType: contentType,
676 }
677 }
678
679 // newX509RequestDELETE initializes an X509Request for a DELETE.
680-func newX509RequestDELETE(url string) *X509Request {
681+func newX509RequestDELETE(url, apiVersion string) *X509Request {
682 return &X509Request{
683 Method: "DELETE",
684 URL: url,
685- APIVersion: baseAPIVersion,
686+ APIVersion: apiVersion,
687 }
688 }
689
690 // newX509RequestPUT initializes an X509Request for a PUT. You may still
691 // need to set further values.
692-func newX509RequestPUT(url string, payload []byte, contentType string) *X509Request {
693+func newX509RequestPUT(url, apiVersion string, payload []byte, contentType string) *X509Request {
694 return &X509Request{
695 Method: "PUT",
696 URL: url,
697- APIVersion: baseAPIVersion,
698+ APIVersion: apiVersion,
699 Payload: payload,
700 ContentType: contentType,
701 }
702
703=== modified file 'x509dispatcher_test.go'
704--- x509dispatcher_test.go 2013-07-10 15:42:42 +0000
705+++ x509dispatcher_test.go 2013-07-12 05:06:27 +0000
706@@ -78,7 +78,8 @@
707 session, err := newX509Session("subscriptionid", "cert.pem")
708 c.Assert(err, IsNil)
709 path := "/foo/bar"
710- request := newX509RequestGET(server.URL + path)
711+ version := "test-version"
712+ request := newX509RequestGET(server.URL + path, version)
713
714 response, err := performX509CurlRequest(session, request)
715 c.Assert(err, IsNil)
716@@ -86,6 +87,7 @@
717
718 httpRequest := <-httpRequests
719 c.Check(httpRequest.Method, Equals, "GET")
720+ c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
721 c.Check(httpRequest.URL.String(), Equals, path)
722 c.Check(httpRequest.BodyContent, HasLen, 0)
723 }
724@@ -101,7 +103,8 @@
725 session, err := newX509Session("subscriptionid", "cert.pem")
726 c.Assert(err, IsNil)
727 path := "/foo/bar"
728- request := newX509RequestGET(server.URL + path)
729+ version := "test-version"
730+ request := newX509RequestGET(server.URL + path, version)
731
732 _, err = performX509CurlRequest(session, request)
733 c.Check(err, ErrorMatches, ".*Number of redirects hit maximum amount.*")
734@@ -114,6 +117,7 @@
735 c.Error("The original request has not been performed.")
736 }
737 c.Check(httpRequest.Method, Equals, "GET")
738+ c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
739 c.Check(httpRequest.URL.String(), Equals, path)
740
741 // _CURL_MAX_REDIRECTS redirected requests have been performed.
742@@ -139,7 +143,8 @@
743 session, err := newX509Session("subscriptionid", "cert.pem")
744 c.Assert(err, IsNil)
745 path := "/foo/bar"
746- request := newX509RequestPOST(server.URL+path, requestBody, requestContentType)
747+ version := "test-version"
748+ request := newX509RequestPOST(server.URL+path, version, requestBody, requestContentType)
749
750 response, err := performX509CurlRequest(session, request)
751 c.Assert(err, IsNil)
752@@ -162,7 +167,8 @@
753 session, err := newX509Session("subscriptionid", "cert.pem")
754 c.Assert(err, IsNil)
755 path := "/foo/bar"
756- request := newX509RequestDELETE(server.URL + path)
757+ version := "test-version"
758+ request := newX509RequestDELETE(server.URL + path, version)
759
760 response, err := performX509CurlRequest(session, request)
761 c.Assert(err, IsNil)
762@@ -170,6 +176,7 @@
763
764 httpRequest := <-httpRequests
765 c.Check(httpRequest.Method, Equals, "DELETE")
766+ c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
767 c.Check(httpRequest.URL.String(), Equals, path)
768 c.Check(httpRequest.BodyContent, HasLen, 0)
769 }
770@@ -184,7 +191,8 @@
771 session, err := newX509Session("subscriptionid", "cert.pem")
772 c.Assert(err, IsNil)
773 path := "/foo/bar"
774- request := newX509RequestPUT(server.URL+path, requestBody, "application/octet-stream")
775+ version := "test-version"
776+ request := newX509RequestPUT(server.URL+path, version, requestBody, "application/octet-stream")
777
778 response, err := performX509CurlRequest(session, request)
779 c.Assert(err, IsNil)
780@@ -193,6 +201,7 @@
781
782 httpRequest := <-httpRequests
783 c.Check(httpRequest.Method, Equals, "PUT")
784+ c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
785 c.Check(httpRequest.URL.String(), Equals, path)
786 c.Check(httpRequest.BodyContent, DeepEquals, requestBody)
787 }
788@@ -211,7 +220,7 @@
789 session, err := newX509Session("subscriptionid", "cert.pem")
790 c.Assert(err, IsNil)
791 path := "/foo/bar"
792- request := newX509RequestGET(server.URL + path)
793+ request := newX509RequestGET(server.URL + path, "testversion")
794
795 response, err := performX509CurlRequest(session, request)
796 c.Assert(err, IsNil)
797
798=== modified file 'x509session.go'
799--- x509session.go 2013-07-10 15:42:42 +0000
800+++ x509session.go 2013-07-12 05:06:27 +0000
801@@ -60,8 +60,8 @@
802 // It returns the response body and/or an error. If the error is a
803 // ServerError, the returned body will be the one received from the server.
804 // For any other kind of error, the returned body will be nil.
805-func (session *x509Session) get(path string) (*x509Response, error) {
806- request := newX509RequestGET(session.composeURL(path))
807+func (session *x509Session) get(path, apiVersion string) (*x509Response, error) {
808+ request := newX509RequestGET(session.composeURL(path), apiVersion)
809 response, err := _X509Dispatcher(session, request)
810 if err != nil {
811 return nil, err
812@@ -76,8 +76,8 @@
813 // For any other kind of error, the returned body will be nil.
814 // Be aware that Azure may perform POST operations asynchronously. If you are
815 // not sure, call blockUntilCompleted() on the response.
816-func (session *x509Session) post(path string, body []byte, contentType string) (*x509Response, error) {
817- request := newX509RequestPOST(session.composeURL(path), body, contentType)
818+func (session *x509Session) post(path, apiVersion string, body []byte, contentType string) (*x509Response, error) {
819+ request := newX509RequestPOST(session.composeURL(path), apiVersion, body, contentType)
820 response, err := _X509Dispatcher(session, request)
821 if err != nil {
822 return nil, err
823@@ -89,8 +89,8 @@
824 // delete performs a DELETE request to the Azure management API.
825 // Be aware that Azure may perform DELETE operations asynchronously. If you
826 // are not sure, call blockUntilCompleted() on the response.
827-func (session *x509Session) delete(path string) (*x509Response, error) {
828- request := newX509RequestDELETE(session.composeURL(path))
829+func (session *x509Session) delete(path, apiVersion string) (*x509Response, error) {
830+ request := newX509RequestDELETE(session.composeURL(path), apiVersion)
831 response, err := _X509Dispatcher(session, request)
832 if err != nil {
833 return response, err
834@@ -102,8 +102,8 @@
835 // put performs a PUT request to the Azure management API.
836 // Be aware that Azure may perform PUT operations asynchronously. If you are
837 // not sure, call blockUntilCompleted() on the response.
838-func (session *x509Session) put(path string, body []byte, contentType string) (*x509Response, error) {
839- request := newX509RequestPUT(session.composeURL(path), body, contentType)
840+func (session *x509Session) put(path, apiVersion string, body []byte, contentType string) (*x509Response, error) {
841+ request := newX509RequestPUT(session.composeURL(path), apiVersion, body, contentType)
842 response, err := _X509Dispatcher(session, request)
843 if err != nil {
844 return nil, err
845
846=== modified file 'x509session_test.go'
847--- x509session_test.go 2013-07-10 15:42:42 +0000
848+++ x509session_test.go 2013-07-12 05:06:27 +0000
849@@ -192,13 +192,15 @@
850 recordedRequests := make([]*X509Request, 0)
851 rigRecordingDispatcher(&recordedRequests)
852
853- receivedResponse, err := session.get(uri)
854+ version := "test-version"
855+ receivedResponse, err := session.get(uri,version)
856 c.Assert(err, IsNil)
857
858 c.Assert(len(recordedRequests), Equals, 1)
859 request := recordedRequests[0]
860 c.Check(request.URL, Equals, AZURE_URL+subscriptionID+"/"+uri)
861 c.Check(request.Method, Equals, "GET")
862+ c.Check(request.APIVersion, Equals, version)
863 c.Check(*receivedResponse, DeepEquals, fixedResponse)
864 }
865
866@@ -207,7 +209,7 @@
867 msg := "could not dispatch request"
868 rigFailingDispatcher(fmt.Errorf(msg))
869
870- body, err := session.get("flop")
871+ body, err := session.get("flop", "version")
872 c.Assert(err, NotNil)
873
874 c.Check(body, IsNil)
875@@ -222,7 +224,7 @@
876 }
877 rigFixedResponseDispatcher(&fixedResponse)
878
879- response, err := session.get("fail")
880+ response, err := session.get("fail", "version")
881 c.Assert(err, NotNil)
882
883 serverError := err.(*ServerError)
884@@ -233,6 +235,7 @@
885 func (suite *x509SessionSuite) TestPostIssuesRequest(c *C) {
886 subscriptionID := "subscriptionID"
887 uri := "resource"
888+ version := "test-version"
889 requestBody := []byte("Request body")
890 requestContentType := "bogusContentType"
891 session, err := newX509Session(subscriptionID, "cert.pem")
892@@ -246,13 +249,14 @@
893 recordedRequests := make([]*X509Request, 0)
894 rigRecordingDispatcher(&recordedRequests)
895
896- receivedResponse, err := session.post(uri, requestBody, requestContentType)
897+ receivedResponse, err := session.post(uri, version, requestBody, requestContentType)
898 c.Assert(err, IsNil)
899
900 c.Assert(len(recordedRequests), Equals, 1)
901 request := recordedRequests[0]
902 c.Check(request.URL, Equals, AZURE_URL+subscriptionID+"/"+uri)
903 c.Check(request.Method, Equals, "POST")
904+ c.Check(request.APIVersion, Equals, version)
905 c.Check(request.ContentType, Equals, requestContentType)
906 c.Check(request.Payload, DeepEquals, requestBody)
907 c.Check(*receivedResponse, DeepEquals, fixedResponse)
908@@ -263,7 +267,7 @@
909 msg := "could not dispatch request"
910 rigFailingDispatcher(fmt.Errorf(msg))
911
912- body, err := session.post("flop", []byte("body"), "contentType")
913+ body, err := session.post("flop", "version", []byte("body"), "contentType")
914 c.Assert(err, NotNil)
915
916 c.Check(body, IsNil)
917@@ -278,7 +282,7 @@
918 }
919 rigFixedResponseDispatcher(&fixedResponse)
920
921- reponse, err := session.post("fail", []byte("request body"), "contentType")
922+ reponse, err := session.post("fail", "version", []byte("request body"), "contentType")
923 c.Assert(err, NotNil)
924
925 serverError := err.(*ServerError)
926@@ -289,6 +293,7 @@
927 func (suite *x509SessionSuite) TestDeleteIssuesRequest(c *C) {
928 subscriptionID := "subscriptionID"
929 uri := "resource"
930+ version := "test-version"
931 session, err := newX509Session(subscriptionID, "cert.pem")
932 c.Assert(err, IsNil)
933 // Record incoming requests, and have them return a given reply.
934@@ -297,7 +302,7 @@
935 recordedRequests := make([]*X509Request, 0)
936 rigRecordingDispatcher(&recordedRequests)
937
938- response, err := session.delete(uri)
939+ response, err := session.delete(uri, version)
940 c.Assert(err, IsNil)
941
942 c.Check(*response, DeepEquals, fixedResponse)
943@@ -305,11 +310,13 @@
944 request := recordedRequests[0]
945 c.Check(request.URL, Equals, AZURE_URL+subscriptionID+"/"+uri)
946 c.Check(request.Method, Equals, "DELETE")
947+ c.Check(request.APIVersion, Equals, version)
948 }
949
950 func (suite *x509SessionSuite) TestPutIssuesRequest(c *C) {
951 subscriptionID := "subscriptionID"
952 uri := "resource"
953+ version := "test-version"
954 requestBody := []byte("Request body")
955 session, err := newX509Session(subscriptionID, "cert.pem")
956 c.Assert(err, IsNil)
957@@ -321,12 +328,13 @@
958 recordedRequests := make([]*X509Request, 0)
959 rigRecordingDispatcher(&recordedRequests)
960
961- _, err = session.put(uri, requestBody, "text/plain")
962+ _, err = session.put(uri, version, requestBody, "text/plain")
963 c.Assert(err, IsNil)
964
965 c.Assert(len(recordedRequests), Equals, 1)
966 request := recordedRequests[0]
967 c.Check(request.URL, Equals, AZURE_URL+subscriptionID+"/"+uri)
968 c.Check(request.Method, Equals, "PUT")
969+ c.Check(request.APIVersion, Equals, version)
970 c.Check(request.Payload, DeepEquals, requestBody)
971 }

Subscribers

People subscribed via source and target branches

to all changes: