Merge lp:~rvb/gwacl/add-network-config into lp:gwacl

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: 153
Merged at revision: 154
Proposed branch: lp:~rvb/gwacl/add-network-config
Merge into: lp:gwacl
Diff against target: 475 lines (+140/-101)
5 files modified
example/management/run.go (+19/-4)
helpers_apiobjects_test.go (+4/-11)
management_base_test.go (+3/-3)
xmlobjects.go (+57/-42)
xmlobjects_test.go (+57/-41)
To merge this branch: bzr merge lp:~rvb/gwacl/add-network-config
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+172518@code.launchpad.net

Commit message

Add support for configuring the network when creating a VM.

Description of the change

This branch's main goal is to allow the user to configure the network using a ConfigurationSet object. It can be used when creating the VM and (hopefully) later on when reconfiguring the VM to open/close ports.

The main trick is that the object we used to call LinuxProvisioningConfiguration is in fact a "generic" ConfigurationSet object which can contain different types of configuration. This is rather bad design on Azure's part but it's easier for us to reflect exactly the structure of Azure's objects in our class hierarchy. This is why I renamed LinuxProvisioningConfiguration into ConfigurationSet and added a utility method to create the other type of ConfigurationSet object: the network configuration object (i.e. a ConfigurationSet object with a type of "NetworkConfiguration").

I changed the DisableSSHPasswordAuthentication boolean into a string because the 'omitempty' parameter would remove the field altogether from the serialized XML when it's false. And we *have to* use 'omitempty' because, when the ConfigurationSet object will be of type NetworkConfiguration, we need that field to be omitted.

I had to tweak the XML used in tests in xmlobjects_test.go because the examples (I /think/, not my doing) where taken straight out of the documentation and are not actually valid (for instance the value for the ports where not integers).

Drive-by fixes:
    - display the host/username/password info in example/management/run.go
    - add the GeoReplicated stuff as a parameter

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Is it really worth adding GeoReplicationEnabled as a parameter to NewCreateStorageServiceInputWithLocation? Go puts you on this slippery slope from "I want optional and named parameters for my function" to "I'll use a Parameter Object" to "I need a constructor for my Parameter Object" to "I want another parameter added to the constructor" to "my constructor needs a Parameter Object."

So unless we need to set the GeoReplicationEnabled all the time, or there is something fundamentally dangerous that requires an explicit choice, I'd just make NewCreateStorageServiceInputWithLocation initialize GeoReplicationEnabled to either "false" or "true," whichever makes more sense. Or if you do make it a parameter, then IMO at least the constructor should take a boolean so that the caller can ignore the weirdness in the field's type!

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

> Is it really worth adding GeoReplicationEnabled as a parameter to
> NewCreateStorageServiceInputWithLocation? Go puts you on this slippery slope
> from "I want optional and named parameters for my function" to "I'll use a
> Parameter Object" to "I need a constructor for my Parameter Object" to "I want
> another parameter added to the constructor" to "my constructor needs a
> Parameter Object."
>
> So unless we need to set the GeoReplicationEnabled all the time, or there is
> something fundamentally dangerous that requires an explicit choice, I'd just
> make NewCreateStorageServiceInputWithLocation initialize GeoReplicationEnabled
> to either "false" or "true," whichever makes more sense. Or if you do make it
> a parameter, then IMO at least the constructor should take a boolean so that
> the caller can ignore the weirdness in the field's type!

You've right, I forgot to say *why* I thought it was important: the geo replication has a very high cost (dixit Scott) and thus I thought that it would be better to force the user to explicitly set it.

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

Also, why only retrieve deployment information in the optional "pause" bit? Isn't this something you might as well do anyway, as part of the test?

Arguably it's not useful if you're not pausing, but then again the same goes for creating the virtual machine in the first place. :) If shutdown fails, for example, you might still want to have a closer look at the instance, perhaps using the information you got from GetDeployment.

Finally, would it be worth adding a few words of how-and-why-this-works documentation to ConfigurationSet?

review: Approve
lp:~rvb/gwacl/add-network-config updated
152. By Raphaël Badin

Review fixes.

153. By Raphaël Badin

Remove test data.

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

> Also, why only retrieve deployment information in the optional "pause" bit?
> Isn't this something you might as well do anyway, as part of the test?
>
> Arguably it's not useful if you're not pausing, but then again the same goes
> for creating the virtual machine in the first place. :) If shutdown fails,
> for example, you might still want to have a closer look at the instance,
> perhaps using the information you got from GetDeployment.

Very true, fixed.

> Finally, would it be worth adding a few words of how-and-why-this-works
> documentation to ConfigurationSet?

Done.

Thanks for the review!

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 02/07/13 20:44, Raphaël Badin wrote:
> I changed the DisableSSHPasswordAuthentication boolean into a string because the 'omitempty' parameter would remove the field altogether from the serialized XML when it's false. And we *have to* use 'omitempty' because, when the ConfigurationSet object will be of type NetworkConfiguration, we need that field to be omitted.

FWIW, this really is shouting that LinuxProvisioningConfiguration is not
the same as a generic ConfigurationSet at all ... which is why I did it
that way to start with.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'example/management/run.go'
2--- example/management/run.go 2013-07-02 00:33:52 +0000
3+++ example/management/run.go 2013-07-02 13:56:26 +0000
4@@ -139,14 +139,16 @@
5 // test with your instance, so we'll use a fixed one. It's not really a
6 // security hazard in such a short-lived private instance.
7 password := "Ubuntu123"
8+ username := "ubuntu"
9 vhdName := makeRandomIdentifier("gwacldisk", 16)
10- configurationSet := gwacl.NewLinuxProvisioningConfiguration(hostname, "ubuntu", password, "TEST_USER_DATA", false)
11+ linuxConfigurationSet := gwacl.NewLinuxProvisioningConfiguration(hostname, username, password, "TEST_USER_DATA", "false")
12+ inputendpoint := gwacl.InputEndpoint{LocalPort: 22, Name: "sshport", Port: 22, Protocol: "TCP"}
13+ networkConfigurationSet := gwacl.NewNetworkConfiguration([]gwacl.InputEndpoint{inputendpoint})
14
15 storageAccount := makeRandomIdentifier("gwacl", 24)
16 storageLabel := makeRandomIdentifier("gwacl", 64)
17 fmt.Printf("Requesting storage account with name '%s' and label '%s'...\n", storageAccount, storageLabel)
18- cssi := gwacl.NewCreateStorageServiceInputWithLocation(storageAccount, storageLabel, location)
19- cssi.GeoReplicationEnabled = "false"
20+ cssi := gwacl.NewCreateStorageServiceInputWithLocation(storageAccount, storageLabel, location, "false")
21 err = api.AddStorageAccount(cssi)
22 checkError(err)
23 fmt.Println("Done requesting storage account\n")
24@@ -162,7 +164,7 @@
25 diskLabel := makeRandomIdentifier("gwacl", 64)
26 vhd := gwacl.NewOSVirtualHardDisk("", diskLabel, diskName, mediaLink, sourceImageName, "Linux")
27 roleName := makeRandomIdentifier("gwaclrole", 16)
28- role := gwacl.NewRole("ExtraSmall", roleName, []gwacl.LinuxProvisioningConfiguration{*configurationSet}, []gwacl.OSVirtualHardDisk{*vhd})
29+ role := gwacl.NewRole("ExtraSmall", roleName, []gwacl.ConfigurationSet{*linuxConfigurationSet, *networkConfigurationSet}, []gwacl.OSVirtualHardDisk{*vhd})
30 machineName := makeRandomIdentifier("gwaclmachine", 20)
31 deployment := gwacl.NewDeploymentForCreateVMDeployment(machineName, "Staging", machineName, []gwacl.Role{*role}, "")
32 err = api.AddDeployment(deployment, hostServiceName)
33@@ -201,6 +203,19 @@
34 fmt.Printf("Got %d instance(s)\n", len(instances))
35 fmt.Println("Done listing VM\n")
36
37+ fmt.Println("Getting deployment info...")
38+ request := &gwacl.GetDeploymentRequest{ServiceName: hostServiceName, DeploymentName: machineName}
39+ deploy, err := api.GetDeployment(request)
40+ checkError(err)
41+ fqdn, err := deploy.GetFQDN()
42+ checkError(err)
43+ fmt.Println("Got deployment info\n")
44+
45+ fmt.Println("host:", fqdn)
46+ fmt.Println("username:", username)
47+ fmt.Println("password:", password)
48+ fmt.Println("")
49+
50 if pause {
51 var wait string
52 fmt.Println("Pausing so you can play with the newly-created VM")
53
54=== modified file 'helpers_apiobjects_test.go'
55--- helpers_apiobjects_test.go 2013-06-28 00:14:46 +0000
56+++ helpers_apiobjects_test.go 2013-07-02 13:56:26 +0000
57@@ -42,20 +42,13 @@
58 Protocol: params.protocol}
59 }
60
61-func makeLinuxProvisioningConfiguration() *LinuxProvisioningConfiguration {
62+func makeLinuxProvisioningConfiguration() *ConfigurationSet {
63 hostname := MakeRandomString(10)
64 username := MakeRandomString(10)
65 password := MakeRandomString(10)
66 userdata := MakeRandomString(10)
67- disableSSH := MakeRandomBool()
68-
69- return &LinuxProvisioningConfiguration{
70- ConfigurationSetType: "LinuxProvisioningConfiguration",
71- Hostname: hostname,
72- Username: username,
73- Password: password,
74- UserData: userdata,
75- DisableSSHPasswordAuthentication: disableSSH}
76+ disableSSH := BoolToString(MakeRandomBool())
77+ return NewLinuxProvisioningConfiguration(hostname, username, password, userdata, disableSSH)
78 }
79
80 func makeOSVirtualHardDisk() *OSVirtualHardDisk {
81@@ -78,7 +71,7 @@
82 RoleName := MakeRandomString(10)
83 RoleType := "PersistentVMRole"
84 config := makeLinuxProvisioningConfiguration()
85- configset := []LinuxProvisioningConfiguration{*config}
86+ configset := []ConfigurationSet{*config}
87
88 return &Role{
89 RoleSize: RoleSize,
90
91=== modified file 'management_base_test.go'
92--- management_base_test.go 2013-07-01 01:14:04 +0000
93+++ management_base_test.go 2013-07-02 13:56:26 +0000
94@@ -495,9 +495,9 @@
95 api := makeAPI(c)
96 recordedRequests := setUpDispatcher("operationID")
97 serviceName := "serviceName"
98- configurationSet := NewLinuxProvisioningConfiguration("testHostname12345", "test", "test123#@!", "user-data", false)
99+ configurationSet := NewLinuxProvisioningConfiguration("testHostname12345", "test", "test123#@!", "user-data", "false")
100 vhd := NewOSVirtualHardDisk("hostCaching", "diskLabel", "diskName", "http://mediaLink", "sourceImageName", "os")
101- role := NewRole("ExtraSmall", "test-role-123", []LinuxProvisioningConfiguration{*configurationSet}, []OSVirtualHardDisk{*vhd})
102+ role := NewRole("ExtraSmall", "test-role-123", []ConfigurationSet{*configurationSet}, []OSVirtualHardDisk{*vhd})
103 deployment := NewDeploymentForCreateVMDeployment("test-machine-name", "Staging", "testLabel", []Role{*role}, "testNetwork")
104 err := api.AddDeployment(deployment, serviceName)
105
106@@ -629,7 +629,7 @@
107 rigFixedResponseDispatcher(&fixedResponse)
108 recordedRequests := make([]*X509Request, 0)
109 rigRecordingDispatcher(&recordedRequests)
110- cssi := NewCreateStorageServiceInputWithLocation("name", "label", "East US")
111+ cssi := NewCreateStorageServiceInputWithLocation("name", "label", "East US", "false")
112
113 err := api.AddStorageAccount(cssi)
114 c.Assert(err, IsNil)
115
116=== modified file 'xmlobjects.go'
117--- xmlobjects.go 2013-07-02 06:08:22 +0000
118+++ xmlobjects.go 2013-07-02 13:56:26 +0000
119@@ -36,31 +36,48 @@
120 }
121
122 //
123-// LinuxProvisioningConfiguration bits
124+// ConfigurationSet bits
125 //
126
127-// TODO: this should contain InputEndpoints objects.
128-type LinuxProvisioningConfiguration struct {
129- ConfigurationSetType string `xml:"ConfigurationSetType"` // "LinuxProvisioningConfiguration"
130- Hostname string `xml:"HostName"`
131- Username string `xml:"UserName"`
132- Password string `xml:"UserPassword"`
133- UserData string `xml:"UserData"`
134- DisableSSHPasswordAuthentication bool `xml:"DisableSshPasswordAuthentication"`
135-}
136-
137-func (c *LinuxProvisioningConfiguration) Serialize() (string, error) {
138+// A ConfigurationSet object can be different things depending on its 'type'.
139+// The types we currently support are:
140+// - LinuxProvisioningConfigurationSet: configuration of a Linux VM
141+// - NetworkConfiguration: configuration of the network of a VM
142+type ConfigurationSet struct {
143+ ConfigurationSetType string `xml:"ConfigurationSetType"` // "ConfigurationSet"
144+
145+ // LinuxProvisioningConfiguration fields.
146+ Hostname string `xml:"HostName,omitempty"`
147+ Username string `xml:"UserName,omitempty"`
148+ Password string `xml:"UserPassword,omitempty"`
149+ UserData string `xml:"UserData,omitempty"`
150+ DisableSSHPasswordAuthentication string `xml:"DisableSshPasswordAuthentication,omitempty"`
151+
152+ // NetworkConfiguration fields.
153+ // We use a pointer in the 'InputEndpoints' field to work around bug:
154+ // https://code.google.com/p/go/issues/detail?id=4168
155+ // We need the whole 'InputEndpoints' element to be omitted when no InputEndpoint objects are
156+ // present (this happens when the ConfigurationSet object has a
157+ // LinuxProvisioningConfiguration type for instance).
158+ InputEndpoints *[]InputEndpoint `xml:"InputEndpoints>InputEndpoint,omitempty"`
159+}
160+
161+func (c *ConfigurationSet) inputEndpoints() []InputEndpoint {
162+ return *c.InputEndpoints
163+}
164+
165+func (c *ConfigurationSet) Serialize() (string, error) {
166 return toxml(c)
167 }
168
169-// NewLinuxProvisioningConfiguration creates and returns a
170-// LinuxProvisioningConfiguration which is used when deploying a Linux VM
171-// instance. Note that UserData is passed to Azure *as-is* which also stores
172-// it as passed, so consider base64 encoding it.
173+// NewLinuxProvisioningConfiguration creates and returns a ConfigurationSet of type
174+// "LinuxProvisioningConfiguration" which is used when deploying a Linux VM instance.
175+// Note that UserData is passed to Azure *as-is* which also stores it as passed, so consider
176+// base64 encoding it.
177 func NewLinuxProvisioningConfiguration(
178 Hostname, Username, Password, UserData string,
179- DisableSSHPasswordAuthentication bool) *LinuxProvisioningConfiguration {
180- return &LinuxProvisioningConfiguration{
181+ DisableSSHPasswordAuthentication string) *ConfigurationSet {
182+ return &ConfigurationSet{
183 ConfigurationSetType: "LinuxProvisioningConfiguration",
184 Hostname: Hostname,
185 Username: Username,
186@@ -70,12 +87,21 @@
187 }
188 }
189
190+// NewNetworkConfiguration creates a ConfigurationSet of type "NetworkConfiguration".
191+func NewNetworkConfiguration(
192+ inputEndpoints []InputEndpoint) *ConfigurationSet {
193+ return &ConfigurationSet{
194+ ConfigurationSetType: "NetworkConfiguration",
195+ InputEndpoints: &inputEndpoints,
196+ }
197+}
198+
199 //
200 // InputEndpoint bits
201 //
202
203 type InputEndpoint struct {
204- LoadBalancedEndpointSetName string `xml:"LoadBalancedEndpointSetName"`
205+ LoadBalancedEndpointSetName string `xml:"LoadBalancedEndpointSetName,omitempty"`
206 LocalPort int `xml:"LocalPort"`
207 Name string `xml:"Name"`
208 Port int `xml:"Port"`
209@@ -245,24 +271,12 @@
210 }
211 }
212
213-//
214-// NetworkConfiguration bits
215-//
216-
217-type NetworkConfiguration struct {
218- InputEndpoints []InputEndpoint `xml:"InputEndpoints>InputEndpoint"`
219-}
220-
221-func (c *NetworkConfiguration) Serialize() (string, error) {
222- return toxml(c)
223-}
224-
225 type Role struct {
226- RoleName string `xml:"RoleName"`
227- RoleType string `xml:"RoleType"` // Always "PersistentVMRole"
228- ConfigurationSets []LinuxProvisioningConfiguration `xml:"ConfigurationSets>ConfigurationSet"`
229- OSVirtualHardDisk []OSVirtualHardDisk `xml:"OSVirtualHardDisk"`
230- RoleSize string `xml:"RoleSize"`
231+ RoleName string `xml:"RoleName"`
232+ RoleType string `xml:"RoleType"` // Always "PersistentVMRole"
233+ ConfigurationSets []ConfigurationSet `xml:"ConfigurationSets>ConfigurationSet"`
234+ OSVirtualHardDisk []OSVirtualHardDisk `xml:"OSVirtualHardDisk"`
235+ RoleSize string `xml:"RoleSize"`
236 }
237
238 //
239@@ -274,7 +288,7 @@
240 }
241
242 func NewRole(RoleSize string, RoleName string,
243- ConfigurationSets []LinuxProvisioningConfiguration, vhds []OSVirtualHardDisk) *Role {
244+ ConfigurationSets []ConfigurationSet, vhds []OSVirtualHardDisk) *Role {
245 return &Role{
246 RoleSize: RoleSize,
247 RoleName: RoleName,
248@@ -560,12 +574,13 @@
249
250 // NewCreateStorageServiceInputWithLocation creates a location-based
251 // CreateStorageServiceInput, with all required fields filled out.
252-func NewCreateStorageServiceInputWithLocation(name, label, location string) *CreateStorageServiceInput {
253+func NewCreateStorageServiceInputWithLocation(name, label, location string, geoReplicationEnabled string) *CreateStorageServiceInput {
254 return &CreateStorageServiceInput{
255- XMLNS: XMLNS,
256- ServiceName: name,
257- Label: base64.StdEncoding.EncodeToString([]byte(label)),
258- Location: location,
259+ XMLNS: XMLNS,
260+ ServiceName: name,
261+ Label: base64.StdEncoding.EncodeToString([]byte(label)),
262+ Location: location,
263+ GeoReplicationEnabled: geoReplicationEnabled,
264 }
265 }
266
267
268=== modified file 'xmlobjects_test.go'
269--- xmlobjects_test.go 2013-07-02 06:08:22 +0000
270+++ xmlobjects_test.go 2013-07-02 13:56:26 +0000
271@@ -20,20 +20,20 @@
272 // Tests for Marshallers
273 //
274
275-func (suite *xmlSuite) TestLinuxProvisioningConfiguration(c *C) {
276+func (suite *xmlSuite) TestConfigurationSet(c *C) {
277 config := makeLinuxProvisioningConfiguration()
278
279 xml, err := config.Serialize()
280 c.Assert(err, IsNil)
281 template := dedent.Dedent(`
282- <LinuxProvisioningConfiguration>
283+ <ConfigurationSet>
284 <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
285 <HostName>%s</HostName>
286 <UserName>%s</UserName>
287 <UserPassword>%s</UserPassword>
288 <UserData>%s</UserData>
289 <DisableSshPasswordAuthentication>%v</DisableSshPasswordAuthentication>
290- </LinuxProvisioningConfiguration>`)
291+ </ConfigurationSet>`)
292 expected := fmt.Sprintf(template, config.Hostname, config.Username,
293 config.Password, config.UserData,
294 config.DisableSSHPasswordAuthentication)
295@@ -76,16 +76,16 @@
296 c.Check(xml, Equals, expected)
297 }
298
299-func (suite *xmlSuite) TestNetworkConfiguration(c *C) {
300+func (suite *xmlSuite) TestConfigurationSetNetworkConfiguration(c *C) {
301 endpoint1 := makeEndpoint(endpointParams{})
302 endpoint2 := makeEndpoint(endpointParams{})
303 endpoints := []InputEndpoint{*endpoint1, *endpoint2}
304- config := &NetworkConfiguration{
305- InputEndpoints: endpoints}
306+ config := NewNetworkConfiguration(endpoints)
307 xml, err := config.Serialize()
308 c.Assert(err, IsNil)
309 template := dedent.Dedent(`
310- <NetworkConfiguration>
311+ <ConfigurationSet>
312+ <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
313 <InputEndpoints>
314 <InputEndpoint>
315 <LoadBalancedEndpointSetName>%s</LoadBalancedEndpointSetName>
316@@ -102,7 +102,7 @@
317 <Protocol>%s</Protocol>
318 </InputEndpoint>
319 </InputEndpoints>
320- </NetworkConfiguration>`)
321+ </ConfigurationSet>`)
322 expected := fmt.Sprintf(template, endpoint1.LoadBalancedEndpointSetName,
323 endpoint1.LocalPort, endpoint1.Name, endpoint1.Port,
324 endpoint1.Protocol, endpoint2.LoadBalancedEndpointSetName,
325@@ -351,14 +351,8 @@
326 <OsVersion>operating-system-version</OsVersion>
327 <ConfigurationSets>
328 <ConfigurationSet>
329- <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
330- <InputEndpoints>
331- <InputEndpoint>
332- <Port>port-number-of-input-endpoint-in-network</Port>
333- <Protocol>protocol-of-input-endpoint-in-network</Protocol>
334- <Vip>virtual-ip-address-of-input-endpoint-in-network</Vip>
335- </InputEndpoint>
336- </InputEndpoints>
337+ <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
338+ <DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
339 </ConfigurationSet>
340 </ConfigurationSets>
341 </Role>
342@@ -369,21 +363,14 @@
343 <ConfigurationSets>
344 <ConfigurationSet>
345 <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
346- <InputEndpoints>
347- <InputEndpoint>
348- <LoadBalancedEndpointSetName>name-of-load-balanced-endpoint-set</LoadBalancedEndpointSetName>
349- <LocalPort>internal-facing-port-of-input-endpoint</LocalPort>
350- <Name>name-of-input-endpoint</Name>
351- <Port>external-facing-port-of-input-endpoint</Port>
352- <LoadBalancerProbe>
353- <Path>path-of-probe</Path>
354- <Port>port-assigned-to-probe</Port>
355- <Protocol>protocol-of-probe-port</Protocol>
356- </LoadBalancerProbe>
357- <Protocol>protocol-of-input-endpoint</Protocol>
358- <Vip>virtual-ip-address-of-input-endpoint</Vip>
359- </InputEndpoint>
360- </InputEndpoints>
361+ <InputEndpoints>
362+ <InputEndpoint>
363+ <Port>2222</Port>
364+ <LocalPort>111</LocalPort>
365+ <Protocol>TCP</Protocol>
366+ <Name>test-name</Name>
367+ </InputEndpoint>
368+ </InputEndpoints>
369 <SubnetNames>
370 <SubnetName>name-of-subnet</SubnetName>
371 </SubnetNames>
372@@ -498,20 +485,27 @@
373 RoleList: []Role{
374 {
375 RoleName: "name-of-role",
376- ConfigurationSets: []LinuxProvisioningConfiguration{
377+ ConfigurationSets: []ConfigurationSet{
378 {
379- ConfigurationSetType: "NetworkConfiguration",
380- DisableSSHPasswordAuthentication: false,
381+ ConfigurationSetType: "LinuxProvisioningConfiguration",
382+ DisableSSHPasswordAuthentication: "false",
383 },
384 },
385 },
386 {
387 RoleName: "name-of-role",
388 RoleType: "PersistentVMRole",
389- ConfigurationSets: []LinuxProvisioningConfiguration{
390+ ConfigurationSets: []ConfigurationSet{
391 {
392- ConfigurationSetType: "NetworkConfiguration",
393- DisableSSHPasswordAuthentication: false,
394+ ConfigurationSetType: "NetworkConfiguration",
395+ InputEndpoints: &[]InputEndpoint{
396+ {
397+ Name: "test-name",
398+ Port: 2222,
399+ LocalPort: 111,
400+ Protocol: "TCP",
401+ },
402+ },
403 },
404 },
405 OSVirtualHardDisk: []OSVirtualHardDisk{
406@@ -597,7 +591,7 @@
407 deploymentSlot := "staging"
408 label := "deploymentLabel"
409 vhd := NewOSVirtualHardDisk("hostCaching", "diskLabel", "diskName", "mediaLink", "sourceImageName", "os")
410- roles := []Role{*NewRole("size", "name", []LinuxProvisioningConfiguration{}, []OSVirtualHardDisk{*vhd})}
411+ roles := []Role{*NewRole("size", "name", []ConfigurationSet{}, []OSVirtualHardDisk{*vhd})}
412 virtualNetworkName := "network"
413
414 deployment := NewDeploymentForCreateVMDeployment(name, deploymentSlot, label, roles, virtualNetworkName)
415@@ -853,7 +847,7 @@
416 rolesize := MakeRandomString(10)
417 rolename := MakeRandomString(10)
418 config := makeLinuxProvisioningConfiguration()
419- configset := []LinuxProvisioningConfiguration{*config}
420+ configset := []ConfigurationSet{*config}
421 vhd := NewOSVirtualHardDisk("hostCaching", "diskLabel", "diskName", "mediaLink", "sourceImageName", "os")
422
423 role := NewRole(rolesize, rolename, configset, []OSVirtualHardDisk{*vhd})
424@@ -867,8 +861,8 @@
425 hostname := MakeRandomString(10)
426 username := MakeRandomString(10)
427 password := MakeRandomString(10)
428+ disablessh := BoolToString(MakeRandomBool())
429 userdata := MakeRandomString(10)
430- disablessh := MakeRandomBool()
431
432 config := NewLinuxProvisioningConfiguration(
433 hostname, username, password, userdata, disablessh)
434@@ -880,6 +874,27 @@
435 c.Check(config.ConfigurationSetType, Equals, "LinuxProvisioningConfiguration")
436 }
437
438+func (suite *xmlSuite) TestNewNetworkConfiguration(c *C) {
439+ name := "name1"
440+ port := 242
441+ localPort := 922
442+ protocol := "TCP"
443+ bName := "bname1"
444+ inputendpoint := InputEndpoint{
445+ LoadBalancedEndpointSetName: bName, LocalPort: localPort, Name: name, Port: port, Protocol: protocol}
446+
447+ config := NewNetworkConfiguration([]InputEndpoint{inputendpoint})
448+ inputEndpoints := *config.InputEndpoints
449+ c.Check(len(inputEndpoints), Equals, 1)
450+ inputEndpoint := inputEndpoints[0]
451+ c.Check(inputEndpoint.Name, Equals, name)
452+ c.Check(inputEndpoint.Port, Equals, port)
453+ c.Check(inputEndpoint.Protocol, Equals, protocol)
454+ c.Check(inputEndpoint.LoadBalancedEndpointSetName, Equals, bName)
455+ c.Check(inputEndpoint.LocalPort, Equals, localPort)
456+ c.Check(config.ConfigurationSetType, Equals, "NetworkConfiguration")
457+}
458+
459 func (suite *xmlSuite) TestNewOSVirtualHardDisk(c *C) {
460 var hostcaching HostCachingType = "ReadWrite"
461 disklabel := MakeRandomString(10)
462@@ -1110,11 +1125,12 @@
463 }
464
465 func (suite *xmlSuite) TestNewCreateStorageServiceInputWithLocation(c *C) {
466- cssi := NewCreateStorageServiceInputWithLocation("name", "label", "location")
467+ cssi := NewCreateStorageServiceInputWithLocation("name", "label", "location", "false")
468 c.Check(cssi.XMLNS, Equals, XMLNS)
469 c.Check(cssi.ServiceName, Equals, "name")
470 c.Check(cssi.Label, Equals, base64.StdEncoding.EncodeToString([]byte("label")))
471 c.Check(cssi.Location, Equals, "location")
472+ c.Check(cssi.GeoReplicationEnabled, Equals, "false")
473 }
474
475 func (suite *xmlSuite) TestBlockListSerialize(c *C) {

Subscribers

People subscribed via source and target branches

to all changes: