Merge lp:~rvb/gwacl/get-deployment into lp:gwacl
- get-deployment
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Raphaël Badin |
Approved revision: | 140 |
Merged at revision: | 135 |
Proposed branch: | lp:~rvb/gwacl/get-deployment |
Merge into: | lp:gwacl |
Diff against target: |
627 lines (+339/-165) 7 files modified
management_base.go (+21/-0) management_base_test.go (+98/-0) storage.go (+5/-6) storage_base.go (+1/-1) vhd_footer.go (+1/-1) xmlobjects.go (+12/-0) xmlobjects_test.go (+201/-157) |
To merge this branch: | bzr merge lp:~rvb/gwacl/get-deployment |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gavin Panella | Approve | ||
Review via email: mp+171488@code.launchpad.net |
Commit message
Add GetDeployment method. Add Deployment.
Description of the change
This branch does two things:
- add a new GetDeployment() to fetch a unique deployment. That will be used in the Azure provider and also in the (upcoming) GetDeployments method when one will filter using only one deployment name.
- add a new GetFQDN() method on a deployment to fetch the hostname (derived from the URL field).
The changes in storage.go and vhd_footer.go are due to "make format".
- 137. By Raphaël Badin
-
Fix variable name.
- 138. By Raphaël Badin
-
Review fixes.
- 139. By Raphaël Badin
-
Use url.QueryEscape().
- 140. By Raphaël Badin
-
Do not use url.QueryEscape().
Raphaël Badin (rvb) wrote : | # |
Thanks for the review.
> [1]
>
> + path := "services/
> "/deployments/" + request.
>
> request.ServiceName and request.
> escaped.
Right. I'm afraid we need to fix some other methods in this file as well.
> [2]
>
> - Size int // How many bytes from the Filesystem data to
> - // upload. *Must* be a multiple of 512.
> + Size int // How many bytes from the Filesystem data to
> upload. *Must* be a multiple of 512.
>
> Is this something that gofmt did?
Not exactly, but gofmt wanted to put the second line of comment at the beginning of the line.
> [3]
>
> - if req.Size % 512 != 0 {
> + if req.Size%512 != 0 {
>
> One problem with using a code formatter is that, when its decision is
> on crack, it's difficult to argue. This change makes the condition
> noticably less readable. A workaround is to use braces:
>
> if (req.Size % 512) != 0 {
>
> gofmt will leave this alone.
>
> Here and elsewhere.
All right.
> [4]
>
> +func (suite *xmlSuite) TestDeploymentG
> + deployment := &Deployment{}
> + err := deployment.
> + c.Assert(err, IsNil)
> + _, err = deployment.
> + c.Assert(err, NotNil)
> +}
>
> Perhaps verify that err is related to parsing, so that this test
> doesn't mask another error later on.
Good point.
> [5]
>
> <Configuration>
>
> Newlines can be added to base64-encoded content without altering its
> meaning. Please can you reformat this line so that it's a little
> shorter?
Okay (but I'm not sure it's that important to be honest, it's not like if someone has to read that line ;)).
Preview Diff
1 | === modified file 'management_base.go' |
2 | --- management_base.go 2013-06-24 08:21:50 +0000 |
3 | +++ management_base.go 2013-06-26 10:55:30 +0000 |
4 | @@ -190,6 +190,27 @@ |
5 | return api.blockUntilCompleted(response) |
6 | } |
7 | |
8 | +type GetDeploymentRequest struct { |
9 | + ServiceName string |
10 | + DeploymentName string |
11 | +} |
12 | + |
13 | +func (api *ManagementAPI) GetDeployment(request *GetDeploymentRequest) (*Deployment, error) { |
14 | + checkPathComponents(request.ServiceName) |
15 | + checkPathComponents(request.DeploymentName) |
16 | + path := "services/hostedservices/" + request.ServiceName + "/deployments/" + request.DeploymentName |
17 | + response, err := api.session.get(path) |
18 | + if err != nil { |
19 | + return nil, err |
20 | + } |
21 | + deployment := Deployment{} |
22 | + err = deployment.Deserialize(response.Body) |
23 | + if err != nil { |
24 | + return nil, err |
25 | + } |
26 | + return &deployment, nil |
27 | +} |
28 | + |
29 | // AddStorageAccount starts the creation of a storage account. This is |
30 | // called a storage service in the Azure API, but nomenclature seems to |
31 | // have changed. |
32 | |
33 | === modified file 'management_base_test.go' |
34 | --- management_base_test.go 2013-06-21 13:33:48 +0000 |
35 | +++ management_base_test.go 2013-06-26 10:55:30 +0000 |
36 | @@ -520,6 +520,104 @@ |
37 | checkOneRequest(c, recordedRequests, expectedURL, []byte{}, "DELETE") |
38 | } |
39 | |
40 | +var getDeploymentResponse = ` |
41 | +<?xml version="1.0"?> |
42 | +<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> |
43 | + <Name>gwaclmachinekjn8minr</Name> |
44 | + <DeploymentSlot>Staging</DeploymentSlot> |
45 | + <PrivateID>53b117c3126a4f1b8b23bc36c2c94dd1</PrivateID> |
46 | + <Status>Running</Status> |
47 | + <Label>WjNkaFkyeHRZV05vYVc1bGEycHVPRzFwYm5JPQ==</Label> |
48 | + <Url>http://53b117c3126a4f1b8b23bc36c2c94dd1.cloudapp.net/</Url> |
49 | + <Configuration>PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53 |
50 | +My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTU |
51 | +xTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZp |
52 | +Y2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJnd2 |
53 | +FjbHJvbGVoYXVxODFyIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQo8 |
54 | +L1NlcnZpY2VDb25maWd1cmF0aW9uPg==</Configuration> |
55 | + <RoleInstanceList> |
56 | + <RoleInstance> |
57 | + <RoleName>gwaclrolehauq81r</RoleName> |
58 | + <InstanceName>gwaclrolehauq81r</InstanceName> |
59 | + <InstanceStatus>ReadyRole</InstanceStatus> |
60 | + <InstanceUpgradeDomain>0</InstanceUpgradeDomain> |
61 | + <InstanceFaultDomain>0</InstanceFaultDomain> |
62 | + <InstanceSize>ExtraSmall</InstanceSize> |
63 | + <InstanceStateDetails/> |
64 | + <IpAddress>10.241.158.13</IpAddress> |
65 | + <PowerState>Started</PowerState> |
66 | + <HostName>gwaclhostsnx7m1co57n</HostName> |
67 | + <RemoteAccessCertificateThumbprint>68db67cd8a6047a6cf6da0f92a7ee67d</RemoteAccessCertificateThumbprint> |
68 | + </RoleInstance> |
69 | + </RoleInstanceList> |
70 | + <UpgradeDomainCount>1</UpgradeDomainCount> |
71 | + <RoleList> |
72 | + <Role i:type="PersistentVMRole"> |
73 | + <RoleName>gwaclrolehauq81r</RoleName> |
74 | + <OsVersion/> |
75 | + <RoleType>PersistentVMRole</RoleType> |
76 | + <ConfigurationSets> |
77 | + <ConfigurationSet i:type="NetworkConfigurationSet"> |
78 | + <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType> |
79 | + <SubnetNames/> |
80 | + </ConfigurationSet> |
81 | + </ConfigurationSets> |
82 | + <DataVirtualHardDisks/> |
83 | + <OSVirtualHardDisk> |
84 | + <HostCaching>ReadWrite</HostCaching> |
85 | + <DiskLabel>gwaclauonntmontirrz9rgltt8d5f4evtjeagbcx7kf8umqhs3t421m21t798ebw</DiskLabel> |
86 | + <DiskName>gwacldiskdvmvahc</DiskName> |
87 | + <MediaLink>http://gwacl3133mh3fs9jck6yk0dh.blob.core.windows.net/vhds/gwacldisk79vobmh.vhd</MediaLink> |
88 | + <SourceImageName>b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_2-LTS-amd64-server-20130624-en-us-30GB</SourceImageName> |
89 | + <OS>Linux</OS> |
90 | + </OSVirtualHardDisk> |
91 | + <RoleSize>ExtraSmall</RoleSize> |
92 | + </Role> |
93 | + </RoleList> |
94 | + <SdkVersion/> |
95 | + <Locked>false</Locked> |
96 | + <RollbackAllowed>false</RollbackAllowed> |
97 | + <CreatedTime>2013-06-25T14:35:22Z</CreatedTime> |
98 | + <LastModifiedTime>2013-06-25T14:48:54Z</LastModifiedTime> |
99 | + <ExtendedProperties/> |
100 | + <PersistentVMDowntime> |
101 | + <StartTime>2013-05-08T22:00:00Z</StartTime> |
102 | + <EndTime>2013-05-10T06:00:00Z</EndTime> |
103 | + <Status>PersistentVMUpdateCompleted</Status> |
104 | + </PersistentVMDowntime> |
105 | + <VirtualIPs> |
106 | + <VirtualIP> |
107 | + <Address>137.117.72.69</Address> |
108 | + <IsDnsProgrammed>true</IsDnsProgrammed> |
109 | + <Name>__PseudoBackEndContractVip</Name> |
110 | + </VirtualIP> |
111 | + </VirtualIPs> |
112 | +</Deployment> |
113 | +` |
114 | + |
115 | +func (suite *managementBaseAPISuite) TestGetDeployment(c *C) { |
116 | + api := makeAPI(c) |
117 | + fixedResponse := x509Response{ |
118 | + StatusCode: http.StatusOK, |
119 | + Body: []byte(getDeploymentResponse), |
120 | + } |
121 | + rigFixedResponseDispatcher(&fixedResponse) |
122 | + recordedRequests := make([]*x509Request, 0) |
123 | + rigRecordingDispatcher(&recordedRequests) |
124 | + |
125 | + serviceName := "serviceName" |
126 | + deploymentName := "gwaclmachinekjn8minr" |
127 | + |
128 | + request := &GetDeploymentRequest{ServiceName: serviceName, DeploymentName: deploymentName} |
129 | + deployment, err := api.GetDeployment(request) |
130 | + c.Assert(err, IsNil) |
131 | + |
132 | + expectedURL := AZURE_URL + api.session.subscriptionId + "/services/hostedservices/" + serviceName + "/deployments/" + deploymentName |
133 | + checkOneRequest(c, &recordedRequests, expectedURL, []byte{}, "GET") |
134 | + |
135 | + c.Check(deployment.Name, Equals, deploymentName) |
136 | +} |
137 | + |
138 | func (suite *managementBaseAPISuite) TestAddStorageAccount(c *C) { |
139 | api := makeAPI(c) |
140 | header := http.Header{} |
141 | |
142 | === modified file 'storage.go' |
143 | --- storage.go 2013-06-25 06:09:00 +0000 |
144 | +++ storage.go 2013-06-26 10:55:30 +0000 |
145 | @@ -121,8 +121,7 @@ |
146 | Container string // Container name in the storage account |
147 | Filename string // Specify the filename in which to store the VHD |
148 | FilesystemData io.Reader // A formatted filesystem, e.g. iso9660. |
149 | - Size int // How many bytes from the Filesystem data to |
150 | - // upload. *Must* be a multiple of 512. |
151 | + Size int // How many bytes from the Filesystem data to upload. *Must* be a multiple of 512. |
152 | } |
153 | |
154 | // CreateInstanceDataVHD will take the supplied filesystem data and create an |
155 | @@ -139,7 +138,7 @@ |
156 | |
157 | var err error |
158 | |
159 | - if req.Size % 512 != 0 { |
160 | + if req.Size%512 != 0 { |
161 | return fmt.Errorf("Size must be a multiple of 512") |
162 | } |
163 | if req.Size > VHD_SIZE-512 { |
164 | @@ -170,8 +169,8 @@ |
165 | err = context.PutPage(&PutPageRequest{ |
166 | Container: req.Container, |
167 | Filename: req.Filename, |
168 | - StartRange: VHD_SIZE-512, // last page of the blob |
169 | - EndRange: VHD_SIZE-1, |
170 | + StartRange: VHD_SIZE - 512, // last page of the blob |
171 | + EndRange: VHD_SIZE - 1, |
172 | Data: dataReader, |
173 | }) |
174 | |
175 | @@ -184,7 +183,7 @@ |
176 | Container: req.Container, |
177 | Filename: req.Filename, |
178 | StartRange: 0, |
179 | - EndRange: req.Size-1, |
180 | + EndRange: req.Size - 1, |
181 | Data: req.FilesystemData, |
182 | }) |
183 | |
184 | |
185 | === modified file 'storage_base.go' |
186 | --- storage_base.go 2013-06-25 00:51:32 +0000 |
187 | +++ storage_base.go 2013-06-26 10:55:30 +0000 |
188 | @@ -439,7 +439,7 @@ |
189 | if req.Size == 0 { |
190 | return fmt.Errorf("Must supply a size for a page blob") |
191 | } |
192 | - if req.Size % 512 != 0 { |
193 | + if req.Size%512 != 0 { |
194 | return fmt.Errorf("Size must be a multiple of 512 bytes") |
195 | } |
196 | case "block": |
197 | |
198 | === modified file 'vhd_footer.go' |
199 | --- vhd_footer.go 2013-06-25 01:06:24 +0000 |
200 | +++ vhd_footer.go 2013-06-26 10:55:30 +0000 |
201 | @@ -20,7 +20,7 @@ |
202 | // example), the easiest way is to use VirtualBox to define a new one, and |
203 | // then do 'tail -c 512 | base64' on that file. |
204 | |
205 | -const VHD_SIZE = 20972032 // This is 20Mib + 512 bytes |
206 | +const VHD_SIZE = 20972032 // This is 20Mib + 512 bytes |
207 | const VHD_FOOTER = ` |
208 | Y29uZWN0aXgAAAACAAEAAP//////////GVKuuHZib3gABAACV2kyawAAAAABQAAAAAAAAAFAAAAC |
209 | WgQRAAAAAv//5y4OEjVapHY7QpuodZNf77j6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
210 | |
211 | === modified file 'xmlobjects.go' |
212 | --- xmlobjects.go 2013-06-21 15:14:41 +0000 |
213 | +++ xmlobjects.go 2013-06-26 10:55:30 +0000 |
214 | @@ -7,6 +7,7 @@ |
215 | "encoding/base64" |
216 | "encoding/xml" |
217 | "fmt" |
218 | + "net/url" |
219 | "regexp" |
220 | "sort" |
221 | "strings" |
222 | @@ -368,6 +369,17 @@ |
223 | ExtendedProperties []ExtendedProperty `xml:"ExtendedProperties>ExtendedProperty,omitempty"` // Only used for "Get Deployment." |
224 | } |
225 | |
226 | +func (deployment *Deployment) GetFQDN() (string, error) { |
227 | + if deployment.URL == "" { |
228 | + return "", fmt.Errorf("Deployment's URL field is empty") |
229 | + } |
230 | + parsedURL, err := url.Parse(deployment.URL) |
231 | + if err != nil { |
232 | + return "", err |
233 | + } |
234 | + return parsedURL.Host, nil |
235 | +} |
236 | + |
237 | func (s *Deployment) Deserialize(data []byte) error { |
238 | return xml.Unmarshal(data, s) |
239 | } |
240 | |
241 | === modified file 'xmlobjects_test.go' |
242 | --- xmlobjects_test.go 2013-06-21 11:54:19 +0000 |
243 | +++ xmlobjects_test.go 2013-06-26 10:55:30 +0000 |
244 | @@ -186,162 +186,163 @@ |
245 | c.Check(xml, Equals, expected) |
246 | } |
247 | |
248 | +// From http://msdn.microsoft.com/en-us/library/windowsazure/ee460804.aspx |
249 | +var deploymentXML = ` |
250 | +<?xml version="1.0" encoding="utf-8"?> |
251 | +<Deployment xmlns="http://schemas.microsoft.com/windowsazure"> |
252 | + <Name>name-of-deployment</Name> |
253 | + <DeploymentSlot>current-deployment-environment</DeploymentSlot> |
254 | + <PrivateID>deployment-id</PrivateID> |
255 | + <Status>status-of-deployment</Status> |
256 | + <Label>base64-encoded-name-of-deployment</Label> |
257 | + <Url>http://name-of-deployment.cloudapp.net</Url> |
258 | + <Configuration>base-64-encoded-configuration-file</Configuration> |
259 | + <RoleInstanceList> |
260 | + <RoleInstance> |
261 | + <RoleName>name-of-role</RoleName> |
262 | + <InstanceName>name-of-role-instance</InstanceName> |
263 | + <InstanceStatus>status-of-role-instance</InstanceStatus> |
264 | + <InstanceUpgradeDomain>update-domain-of-role-instance</InstanceUpgradeDomain> |
265 | + <InstanceFaultDomain>fault-domain-of-role-instance</InstanceFaultDomain> |
266 | + <InstanceSize>size-of-role-instance</InstanceSize> |
267 | + <InstanceStateDetails>state-of-role-instance</InstanceStateDetails> |
268 | + <InstanceErrorCode>error-code-returned-for-role-instance</InstanceErrorCode> |
269 | + <IpAddress>ip-address-of-role-instance</IpAddress> |
270 | + <InstanceEndpoints> |
271 | + <InstanceEndpoint> |
272 | + <Name>name-of-endpoint</Name> |
273 | + <Vip>virtual-ip-address-of-instance-endpoint</Vip> |
274 | + <PublicPort>1234</PublicPort> |
275 | + <LocalPort>5678</LocalPort> |
276 | + <Protocol>protocol-of-instance-endpoint</Protocol> |
277 | + </InstanceEndpoint> |
278 | + </InstanceEndpoints> |
279 | + <PowerState>state-of-role-instance</PowerState> |
280 | + <HostName>dns-name-of-service</HostName> |
281 | + <RemoteAccessCertificateThumbprint>cert-thumbprint-for-remote-access</RemoteAccessCertificateThumbprint> |
282 | + </RoleInstance> |
283 | + </RoleInstanceList> |
284 | + <UpgradeStatus> |
285 | + <UpgradeType>auto|manual</UpgradeType> |
286 | + <CurrentUpgradeDomainState>before|during</CurrentUpgradeDomainState> |
287 | + <CurrentUpgradeDomain>n</CurrentUpgradeDomain> |
288 | + </UpgradeStatus> |
289 | + <UpgradeDomainCount>number-of-upgrade-domains-in-deployment</UpgradeDomainCount> |
290 | + <RoleList> |
291 | + <Role> |
292 | + <RoleName>name-of-role</RoleName> |
293 | + <OsVersion>operating-system-version</OsVersion> |
294 | + <ConfigurationSets> |
295 | + <ConfigurationSet> |
296 | + <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType> |
297 | + <InputEndpoints> |
298 | + <InputEndpoint> |
299 | + <Port>port-number-of-input-endpoint-in-network</Port> |
300 | + <Protocol>protocol-of-input-endpoint-in-network</Protocol> |
301 | + <Vip>virtual-ip-address-of-input-endpoint-in-network</Vip> |
302 | + </InputEndpoint> |
303 | + </InputEndpoints> |
304 | + </ConfigurationSet> |
305 | + </ConfigurationSets> |
306 | + </Role> |
307 | + <Role> |
308 | + <RoleName>name-of-role</RoleName> |
309 | + <OsVersion>operating-system-version</OsVersion> |
310 | + <RoleType>PersistentVMRole</RoleType> |
311 | + <ConfigurationSets> |
312 | + <ConfigurationSet> |
313 | + <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType> |
314 | + <InputEndpoints> |
315 | + <InputEndpoint> |
316 | + <LoadBalancedEndpointSetName>name-of-load-balanced-endpoint-set</LoadBalancedEndpointSetName> |
317 | + <LocalPort>internal-facing-port-of-input-endpoint</LocalPort> |
318 | + <Name>name-of-input-endpoint</Name> |
319 | + <Port>external-facing-port-of-input-endpoint</Port> |
320 | + <LoadBalancerProbe> |
321 | + <Path>path-of-probe</Path> |
322 | + <Port>port-assigned-to-probe</Port> |
323 | + <Protocol>protocol-of-probe-port</Protocol> |
324 | + </LoadBalancerProbe> |
325 | + <Protocol>protocol-of-input-endpoint</Protocol> |
326 | + <Vip>virtual-ip-address-of-input-endpoint</Vip> |
327 | + </InputEndpoint> |
328 | + </InputEndpoints> |
329 | + <SubnetNames> |
330 | + <SubnetName>name-of-subnet</SubnetName> |
331 | + </SubnetNames> |
332 | + </ConfigurationSet> |
333 | + </ConfigurationSets> |
334 | + <AvailabilitySetName>name-of-availability-set</AvailabilitySetName> |
335 | + <DataVirtualHardDisks> |
336 | + <DataVirtualHardDisk> |
337 | + <HostCaching>host-caching-mode-of-data-disk</HostCaching> |
338 | + <DiskName>name-of-data-disk</DiskName> |
339 | + <Lun>logical-unit-number-of-data-disk</Lun> |
340 | + <LogicalDiskSizeInGB>size-of-data-disk</LogicalDiskSizeInGB> |
341 | + <MediaLink>path-to-vhd</MediaLink> |
342 | + </DataVirtualHardDisk> |
343 | + </DataVirtualHardDisks> |
344 | + <OSVirtualHardDisk> |
345 | + <HostCaching>host-caching-mode-of-os-disk</HostCaching> |
346 | + <DiskName>name-of-os-disk</DiskName> |
347 | + <MediaLink>path-to-vhd</MediaLink> |
348 | + <SourceImageName>image-used-to-create-os-disk</SourceImageName> |
349 | + <OS>operating-system-on-os-disk</OS> |
350 | + </OSVirtualHardDisk> |
351 | + <RoleSize>size-of-instance</RoleSize> |
352 | + </Role> |
353 | + </RoleList> |
354 | + <SdkVersion>sdk-version-used-to-create-package</SdkVersion> |
355 | + <Locked>status-of-deployment-write-allowed</Locked> |
356 | + <RollbackAllowed>rollback-operation-allowed</RollbackAllowed> |
357 | + <VirtualNetworkName>name-of-virtual-network</VirtualNetworkName> |
358 | + <Dns> |
359 | + <DnsServers> |
360 | + <DnsServer> |
361 | + <Name>name-of-dns-server</Name> |
362 | + <Address>address-of-dns-server</Address> |
363 | + </DnsServer> |
364 | + </DnsServers> |
365 | + </Dns> |
366 | + <ExtendedProperties> |
367 | + <ExtendedProperty> |
368 | + <Name>name-of-property</Name> |
369 | + <Value>value-of-property</Value> |
370 | + </ExtendedProperty> |
371 | + </ExtendedProperties> |
372 | + <PersistentVMDowntime> |
373 | + <StartTime>start-of-downtime</StartTime> |
374 | + <EndTime>end-of-downtime</EndTime> |
375 | + <Status>status-of-downtime</Status> |
376 | + </PersistentVMDowntime> |
377 | + <VirtualIPs> |
378 | + <VirtualIP> |
379 | + <Address>virtual-ip-address-of-deployment</Address> |
380 | + </VirtualIP> |
381 | + </VirtualIPs> |
382 | + <ExtensionConfiguration> |
383 | + <AllRoles> |
384 | + <Extension> |
385 | + <Id>identifier-of-extension</Id> |
386 | + </Extension> |
387 | + ... |
388 | + </AllRoles> |
389 | + <NamedRoles> |
390 | + <Role> |
391 | + <RoleName>role_name1</RoleName> |
392 | + <Extensions> |
393 | + <Extension> |
394 | + <Id>identifier-of-extension</Id> |
395 | + </Extension> |
396 | + ... |
397 | + </Extensions> |
398 | + </Role> |
399 | + </NamedRoles> |
400 | + </ExtensionConfiguration> |
401 | +</Deployment> |
402 | +` |
403 | + |
404 | func (suite *xmlSuite) TestDeploymentWRTGetDeployment(c *C) { |
405 | - // From http://msdn.microsoft.com/en-us/library/windowsazure/ee460804.aspx |
406 | - input := ` |
407 | - <?xml version="1.0" encoding="utf-8"?> |
408 | - <Deployment xmlns="http://schemas.microsoft.com/windowsazure"> |
409 | - <Name>name-of-deployment</Name> |
410 | - <DeploymentSlot>current-deployment-environment</DeploymentSlot> |
411 | - <PrivateID>deployment-id</PrivateID> |
412 | - <Status>status-of-deployment</Status> |
413 | - <Label>base64-encoded-name-of-deployment</Label> |
414 | - <Url>deployment-url</Url> |
415 | - <Configuration>base-64-encoded-configuration-file</Configuration> |
416 | - <RoleInstanceList> |
417 | - <RoleInstance> |
418 | - <RoleName>name-of-role</RoleName> |
419 | - <InstanceName>name-of-role-instance</InstanceName> |
420 | - <InstanceStatus>status-of-role-instance</InstanceStatus> |
421 | - <InstanceUpgradeDomain>update-domain-of-role-instance</InstanceUpgradeDomain> |
422 | - <InstanceFaultDomain>fault-domain-of-role-instance</InstanceFaultDomain> |
423 | - <InstanceSize>size-of-role-instance</InstanceSize> |
424 | - <InstanceStateDetails>state-of-role-instance</InstanceStateDetails> |
425 | - <InstanceErrorCode>error-code-returned-for-role-instance</InstanceErrorCode> |
426 | - <IpAddress>ip-address-of-role-instance</IpAddress> |
427 | - <InstanceEndpoints> |
428 | - <InstanceEndpoint> |
429 | - <Name>name-of-endpoint</Name> |
430 | - <Vip>virtual-ip-address-of-instance-endpoint</Vip> |
431 | - <PublicPort>1234</PublicPort> |
432 | - <LocalPort>5678</LocalPort> |
433 | - <Protocol>protocol-of-instance-endpoint</Protocol> |
434 | - </InstanceEndpoint> |
435 | - </InstanceEndpoints> |
436 | - <PowerState>state-of-role-instance</PowerState> |
437 | - <HostName>dns-name-of-service</HostName> |
438 | - <RemoteAccessCertificateThumbprint>cert-thumbprint-for-remote-access</RemoteAccessCertificateThumbprint> |
439 | - </RoleInstance> |
440 | - </RoleInstanceList> |
441 | - <UpgradeStatus> |
442 | - <UpgradeType>auto|manual</UpgradeType> |
443 | - <CurrentUpgradeDomainState>before|during</CurrentUpgradeDomainState> |
444 | - <CurrentUpgradeDomain>n</CurrentUpgradeDomain> |
445 | - </UpgradeStatus> |
446 | - <UpgradeDomainCount>number-of-upgrade-domains-in-deployment</UpgradeDomainCount> |
447 | - <RoleList> |
448 | - <Role> |
449 | - <RoleName>name-of-role</RoleName> |
450 | - <OsVersion>operating-system-version</OsVersion> |
451 | - <ConfigurationSets> |
452 | - <ConfigurationSet> |
453 | - <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType> |
454 | - <InputEndpoints> |
455 | - <InputEndpoint> |
456 | - <Port>port-number-of-input-endpoint-in-network</Port> |
457 | - <Protocol>protocol-of-input-endpoint-in-network</Protocol> |
458 | - <Vip>virtual-ip-address-of-input-endpoint-in-network</Vip> |
459 | - </InputEndpoint> |
460 | - </InputEndpoints> |
461 | - </ConfigurationSet> |
462 | - </ConfigurationSets> |
463 | - </Role> |
464 | - <Role> |
465 | - <RoleName>name-of-role</RoleName> |
466 | - <OsVersion>operating-system-version</OsVersion> |
467 | - <RoleType>PersistentVMRole</RoleType> |
468 | - <ConfigurationSets> |
469 | - <ConfigurationSet> |
470 | - <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType> |
471 | - <InputEndpoints> |
472 | - <InputEndpoint> |
473 | - <LoadBalancedEndpointSetName>name-of-load-balanced-endpoint-set</LoadBalancedEndpointSetName> |
474 | - <LocalPort>internal-facing-port-of-input-endpoint</LocalPort> |
475 | - <Name>name-of-input-endpoint</Name> |
476 | - <Port>external-facing-port-of-input-endpoint</Port> |
477 | - <LoadBalancerProbe> |
478 | - <Path>path-of-probe</Path> |
479 | - <Port>port-assigned-to-probe</Port> |
480 | - <Protocol>protocol-of-probe-port</Protocol> |
481 | - </LoadBalancerProbe> |
482 | - <Protocol>protocol-of-input-endpoint</Protocol> |
483 | - <Vip>virtual-ip-address-of-input-endpoint</Vip> |
484 | - </InputEndpoint> |
485 | - </InputEndpoints> |
486 | - <SubnetNames> |
487 | - <SubnetName>name-of-subnet</SubnetName> |
488 | - </SubnetNames> |
489 | - </ConfigurationSet> |
490 | - </ConfigurationSets> |
491 | - <AvailabilitySetName>name-of-availability-set</AvailabilitySetName> |
492 | - <DataVirtualHardDisks> |
493 | - <DataVirtualHardDisk> |
494 | - <HostCaching>host-caching-mode-of-data-disk</HostCaching> |
495 | - <DiskName>name-of-data-disk</DiskName> |
496 | - <Lun>logical-unit-number-of-data-disk</Lun> |
497 | - <LogicalDiskSizeInGB>size-of-data-disk</LogicalDiskSizeInGB> |
498 | - <MediaLink>path-to-vhd</MediaLink> |
499 | - </DataVirtualHardDisk> |
500 | - </DataVirtualHardDisks> |
501 | - <OSVirtualHardDisk> |
502 | - <HostCaching>host-caching-mode-of-os-disk</HostCaching> |
503 | - <DiskName>name-of-os-disk</DiskName> |
504 | - <MediaLink>path-to-vhd</MediaLink> |
505 | - <SourceImageName>image-used-to-create-os-disk</SourceImageName> |
506 | - <OS>operating-system-on-os-disk</OS> |
507 | - </OSVirtualHardDisk> |
508 | - <RoleSize>size-of-instance</RoleSize> |
509 | - </Role> |
510 | - </RoleList> |
511 | - <SdkVersion>sdk-version-used-to-create-package</SdkVersion> |
512 | - <Locked>status-of-deployment-write-allowed</Locked> |
513 | - <RollbackAllowed>rollback-operation-allowed</RollbackAllowed> |
514 | - <VirtualNetworkName>name-of-virtual-network</VirtualNetworkName> |
515 | - <Dns> |
516 | - <DnsServers> |
517 | - <DnsServer> |
518 | - <Name>name-of-dns-server</Name> |
519 | - <Address>address-of-dns-server</Address> |
520 | - </DnsServer> |
521 | - </DnsServers> |
522 | - </Dns> |
523 | - <ExtendedProperties> |
524 | - <ExtendedProperty> |
525 | - <Name>name-of-property</Name> |
526 | - <Value>value-of-property</Value> |
527 | - </ExtendedProperty> |
528 | - </ExtendedProperties> |
529 | - <PersistentVMDowntime> |
530 | - <StartTime>start-of-downtime</StartTime> |
531 | - <EndTime>end-of-downtime</EndTime> |
532 | - <Status>status-of-downtime</Status> |
533 | - </PersistentVMDowntime> |
534 | - <VirtualIPs> |
535 | - <VirtualIP> |
536 | - <Address>virtual-ip-address-of-deployment</Address> |
537 | - </VirtualIP> |
538 | - </VirtualIPs> |
539 | - <ExtensionConfiguration> |
540 | - <AllRoles> |
541 | - <Extension> |
542 | - <Id>identifier-of-extension</Id> |
543 | - </Extension> |
544 | - ... |
545 | - </AllRoles> |
546 | - <NamedRoles> |
547 | - <Role> |
548 | - <RoleName>role_name1</RoleName> |
549 | - <Extensions> |
550 | - <Extension> |
551 | - <Id>identifier-of-extension</Id> |
552 | - </Extension> |
553 | - ... |
554 | - </Extensions> |
555 | - </Role> |
556 | - </NamedRoles> |
557 | - </ExtensionConfiguration> |
558 | - </Deployment> |
559 | - ` |
560 | expected := &Deployment{ |
561 | XMLNS: "http://schemas.microsoft.com/windowsazure", |
562 | Name: "name-of-deployment", |
563 | @@ -349,7 +350,7 @@ |
564 | PrivateID: "deployment-id", |
565 | Status: "status-of-deployment", |
566 | Label: "base64-encoded-name-of-deployment", |
567 | - URL: "deployment-url", |
568 | + URL: "http://name-of-deployment.cloudapp.net", |
569 | Configuration: "base-64-encoded-configuration-file", |
570 | RoleInstanceList: []RoleInstance{ |
571 | { |
572 | @@ -426,11 +427,54 @@ |
573 | }, |
574 | } |
575 | observed := &Deployment{} |
576 | - err := observed.Deserialize([]byte(input)) |
577 | + err := observed.Deserialize([]byte(deploymentXML)) |
578 | c.Assert(err, IsNil) |
579 | c.Assert(observed, DeepEquals, expected) |
580 | } |
581 | |
582 | +func (suite *xmlSuite) TestDeploymentGetFQDNExtractsFQDN(c *C) { |
583 | + deployment := &Deployment{} |
584 | + err := deployment.Deserialize([]byte(deploymentXML)) |
585 | + c.Assert(err, IsNil) |
586 | + fqdn, err := deployment.GetFQDN() |
587 | + c.Assert(err, IsNil) |
588 | + c.Assert(fqdn, Equals, "name-of-deployment.cloudapp.net") |
589 | +} |
590 | + |
591 | +var deploymentXMLEmptyURL = ` |
592 | +<?xml version="1.0" encoding="utf-8"?> |
593 | +<Deployment xmlns="http://schemas.microsoft.com/windowsazure"> |
594 | + <Name>name-of-deployment</Name> |
595 | + <Label>base64-encoded-name-of-deployment</Label> |
596 | + <Url></Url> |
597 | +</Deployment> |
598 | +` |
599 | + |
600 | +func (suite *xmlSuite) TestDeploymentGetFQDNErrorsIfURLIsEmpty(c *C) { |
601 | + deployment := &Deployment{} |
602 | + err := deployment.Deserialize([]byte(deploymentXMLEmptyURL)) |
603 | + c.Assert(err, IsNil) |
604 | + _, err = deployment.GetFQDN() |
605 | + c.Check(err, ErrorMatches, ".*URL field is empty.*") |
606 | +} |
607 | + |
608 | +var deploymentXMLFaultyURL = ` |
609 | +<?xml version="1.0" encoding="utf-8"?> |
610 | +<Deployment xmlns="http://schemas.microsoft.com/windowsazure"> |
611 | + <Name>name-of-deployment</Name> |
612 | + <Label>base64-encoded-name-of-deployment</Label> |
613 | + <Url>%z</Url> |
614 | +</Deployment> |
615 | +` |
616 | + |
617 | +func (suite *xmlSuite) TestDeploymentGetFQDNErrorsIfURLCannotBeParsed(c *C) { |
618 | + deployment := &Deployment{} |
619 | + err := deployment.Deserialize([]byte(deploymentXMLFaultyURL)) |
620 | + c.Assert(err, IsNil) |
621 | + _, err = deployment.GetFQDN() |
622 | + c.Check(err, ErrorMatches, ".*invalid URL.*") |
623 | +} |
624 | + |
625 | func (suite *xmlSuite) TestNewDeploymentForCreateVMDeployment(c *C) { |
626 | name := "deploymentName" |
627 | deploymentSlot := "staging" |
Looks good :)
[1]
+ path := "services/ hostedservices/ " + request.ServiceName + "/deployments/" + request. DeploymentName
request.ServiceName and request. DeploymentName need to be query
escaped.
[2]
- Size int // How many bytes from the Filesystem data to
- // upload. *Must* be a multiple of 512.
+ Size int // How many bytes from the Filesystem data to upload. *Must* be a multiple of 512.
Is this something that gofmt did?
[3]
- if req.Size % 512 != 0 {
+ if req.Size%512 != 0 {
One problem with using a code formatter is that, when its decision is
on crack, it's difficult to argue. This change makes the condition
noticably less readable. A workaround is to use braces:
if (req.Size % 512) != 0 {
gofmt will leave this alone.
Here and elsewhere.
[4]
+func (suite *xmlSuite) TestDeploymentG etFQDNErrorsIfU RLCannotBeParse d(c *C) { Deserialize( []byte( deploymentXMLFa ultyURL) ) GetFQDN( )
+ deployment := &Deployment{}
+ err := deployment.
+ c.Assert(err, IsNil)
+ _, err = deployment.
+ c.Assert(err, NotNil)
+}
Perhaps verify that err is related to parsing, so that this test
doesn't mask another error later on.
[5]
<Configuration> PFNlcnZpY2VDb25 maWd1cmF0aW9uIH htbG5zOnhzZD0ia HR0cD.. .
Newlines can be added to base64-encoded content without altering its
meaning. Please can you reformat this line so that it's a little
shorter?