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

Proposed by Julian Edwards on 2013-07-12
Status: Merged
Approved by: Julian Edwards on 2013-07-12
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) 2013-07-12 Approve on 2013-07-12
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.
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.

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: