Merge lp:~rvb/gwacl/get-deployment into lp:gwacl

Proposed by Raphaël Badin
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
Reviewer Review Type Date Requested Status
Gavin Panella Approve
Review via email: mp+171488@code.launchpad.net

Commit message

Add GetDeployment method. Add Deployment.GetFQDN() method.

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".

To post a comment you must log in.
lp:~rvb/gwacl/get-deployment updated
137. By Raphaël Badin

Fix variable name.

Revision history for this message
Gavin Panella (allenap) wrote :

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) TestDeploymentGetFQDNErrorsIfURLCannotBeParsed(c *C) {
+    deployment := &Deployment{}
+    err := deployment.Deserialize([]byte(deploymentXMLFaultyURL))
+    c.Assert(err, IsNil)
+    _, err = deployment.GetFQDN()
+    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>PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cD...

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?

review: Approve
lp:~rvb/gwacl/get-deployment updated
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().

Revision history for this message
Raphaël Badin (rvb) wrote :

Thanks for the review.

> [1]
>
> +    path := "services/hostedservices/" + request.ServiceName +
> "/deployments/" + request.DeploymentName
>
> request.ServiceName and request.DeploymentName need to be query
> 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) TestDeploymentGetFQDNErrorsIfURLCannotBeParsed(c *C) {
> +    deployment := &Deployment{}
> +    err := deployment.Deserialize([]byte(deploymentXMLFaultyURL))
> +    c.Assert(err, IsNil)
> +    _, err = deployment.GetFQDN()
> +    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>PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cD...
>
> 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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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"

Subscribers

People subscribed via source and target branches

to all changes: