Merge lp:~allenap/gwacl/list-instances-2 into lp:gwacl

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: 132
Merged at revision: 130
Proposed branch: lp:~allenap/gwacl/list-instances-2
Merge into: lp:gwacl
Diff against target: 216 lines (+26/-119)
3 files modified
example/management/run.go (+6/-0)
management.go (+11/-13)
management_test.go (+9/-106)
To merge this branch: bzr merge lp:~allenap/gwacl/list-instances-2
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+171097@code.launchpad.net

Commit message

In ListInstances, only return instances for a single service.

Previously it returned instances for all services.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

Looks good.

I see you've changed ListInstances() to take a struct instead of the hosted service name as a string like all the other methods in the management API. Now I'm on the fence with this: I think we should change all the methods to take structs but maybe that's a change we should do all at once; on the other hand, starting to do it right now with new methods will save us time updating call sites in the provider later; and given how painful it is to juggle with dependencies versions in Go, maybe your choice is the right one after all…

[0]

> 216 lines (+26/-119) 3 files modified

Nice :)

[1]

30 + ServiceName string
31 +}
32 +
33 +// ListInstances returns a slice of all instances for all deployments for the
34 +// given service.

I'd keep saying "hosted service name" instead of just "service name" for consistency (and more importantly because that's how the doc refers to a service).

review: Approve
lp:~allenap/gwacl/list-instances-2 updated
132. By Gavin Panella

Update docstring.

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

> I see you've changed ListInstances() to take a struct instead of the hosted
> service name as a string like all the other methods in the management API.
> Now I'm on the fence with this: I think we should change all the methods to
> take structs but maybe that's a change we should do all at once; on the other
> hand, starting to do it right now with new methods will save us time updating
> call sites in the provider later; and given how painful it is to juggle with
> dependencies versions in Go, maybe your choice is the right one after all…

I think we're safe to do it bit by bit, and I would prefer to do it
that way. There's no need to do it all at once, so we shouldn't force
ourselves to do it all at once. Go will not let us pass the wrong
thing so we'll have early warning when we've got it wrong, and how.

> [1]
>
> 30      +    ServiceName string
> 31      +}
> 32      +
> 33      +// ListInstances returns a slice of all instances for all deployments
> for the
> 34      +// given service.
>
> I'd keep saying "hosted service name" instead of just "service name" for
> consistency (and more importantly because that's how the doc refers to a
> service).

Changed.

Thanks for the review!

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-06-19 21:01:54 +0000
3+++ example/management/run.go 2013-06-24 16:05:33 +0000
4@@ -148,6 +148,12 @@
5 checkError(err)
6 fmt.Println("Done starting VM\n")
7
8+ fmt.Println("Listing VM...")
9+ instances, err := api.ListInstances(&gwacl.ListInstancesRequest{hostServiceName})
10+ checkError(err)
11+ fmt.Printf("Got %d instance(s)\n", len(instances))
12+ fmt.Println("Done listing VM\n")
13+
14 fmt.Println("Stopping VM...")
15 err = api.PerformRoleOperation(hostServiceName, deployment.Name, role.RoleName, gwacl.ShutdownRoleOperation)
16 checkError(err)
17
18=== modified file 'management.go'
19--- management.go 2013-06-21 15:14:41 +0000
20+++ management.go 2013-06-24 16:05:33 +0000
21@@ -3,22 +3,20 @@
22
23 package gwacl
24
25-// ListInstances returns a slice of all instances for all deployments for all
26-// services reachable with the user's credentials.
27-func (api *ManagementAPI) ListInstances() ([]RoleInstance, error) {
28- services, err := api.ListHostedServices()
29+type ListInstancesRequest struct {
30+ ServiceName string
31+}
32+
33+// ListInstances returns a slice of all instances for all deployments for the
34+// given hosted service name.
35+func (api *ManagementAPI) ListInstances(request *ListInstancesRequest) ([]RoleInstance, error) {
36+ instances := []RoleInstance{}
37+ properties, err := api.GetHostedServiceProperties(request.ServiceName, true)
38 if err != nil {
39 return nil, err
40 }
41- instances := []RoleInstance{}
42- for _, service := range services {
43- properties, err := api.GetHostedServiceProperties(service.ServiceName, true)
44- if err != nil {
45- return nil, err
46- }
47- for _, deployment := range properties.Deployments {
48- instances = append(instances, deployment.RoleInstanceList...)
49- }
50+ for _, deployment := range properties.Deployments {
51+ instances = append(instances, deployment.RoleInstanceList...)
52 }
53 return instances, nil
54 }
55
56=== modified file 'management_test.go'
57--- management_test.go 2013-06-22 14:08:31 +0000
58+++ management_test.go 2013-06-24 16:05:33 +0000
59@@ -14,22 +14,7 @@
60
61 // TestListInstances goes through the happy path for ListInstances.
62 func (suite *managementAPISuite) TestListInstances(c *C) {
63- // First response is the list of services.
64- services := HostedServiceDescriptorList{
65- HostedServices: []HostedServiceDescriptor{
66- {ServiceName: "S1"},
67- {ServiceName: "S2"},
68- },
69- }
70- servicesXML, err := services.Serialize()
71- c.Assert(err, IsNil)
72- servicesResponse := DispatcherResponse{
73- response: &x509Response{
74- Body: []byte(servicesXML),
75- StatusCode: http.StatusOK,
76- },
77- }
78- // Second response is the list of properties for "S1".
79+ // The list of properties for "S1".
80 propertiesS1 := HostedService{
81 ServiceName: "S1",
82 Deployments: []Deployment{
83@@ -55,125 +40,43 @@
84 StatusCode: http.StatusOK,
85 },
86 }
87- // Third response is the list of properties for "S2".
88- propertiesS2 := HostedService{
89- ServiceName: "S2",
90- Deployments: []Deployment{
91- {
92- RoleInstanceList: []RoleInstance{
93- {RoleName: "five"},
94- {RoleName: "six"},
95- },
96- },
97- {
98- RoleInstanceList: []RoleInstance{
99- {RoleName: "seven"},
100- {RoleName: "eight"},
101- },
102- },
103- },
104- }
105- propertiesS2XML, err := propertiesS2.Serialize()
106- c.Assert(err, IsNil)
107- propertiesS2Response := DispatcherResponse{
108- response: &x509Response{
109- Body: []byte(propertiesS2XML),
110- StatusCode: http.StatusOK,
111- },
112- }
113- // Rig the prepared responses in.
114+ // Rig the prepared response in.
115 record := []*x509Request{}
116 rigRecordingPreparedResponseDispatcher(
117- &record, []DispatcherResponse{
118- servicesResponse,
119- propertiesS1Response,
120- propertiesS2Response,
121- },
122+ &record, []DispatcherResponse{propertiesS1Response},
123 )
124 // Finally, exercise ListInstances.
125 api := makeAPI(c)
126- instances, err := api.ListInstances()
127+ request := &ListInstancesRequest{ServiceName: propertiesS1.ServiceName}
128+ instances, err := api.ListInstances(request)
129 c.Assert(err, IsNil)
130 c.Check(instances, DeepEquals, []RoleInstance{
131 propertiesS1.Deployments[0].RoleInstanceList[0],
132 propertiesS1.Deployments[0].RoleInstanceList[1],
133 propertiesS1.Deployments[1].RoleInstanceList[0],
134 propertiesS1.Deployments[1].RoleInstanceList[1],
135- propertiesS2.Deployments[0].RoleInstanceList[0],
136- propertiesS2.Deployments[0].RoleInstanceList[1],
137- propertiesS2.Deployments[1].RoleInstanceList[0],
138- propertiesS2.Deployments[1].RoleInstanceList[1],
139 })
140- // The first request was for the services.
141+ // The only request is for S1's properties
142 c.Assert(len(record), Not(Equals), 0)
143 c.Check(record[0], DeepEquals, &x509Request{
144 APIVersion: baseAPIVersion,
145- URL: AZURE_URL + "subscriptionId/services/hostedservices",
146- Method: "GET",
147- })
148- // The second for S1's properties
149- c.Assert(len(record), Not(Equals), 1)
150- c.Check(record[1], DeepEquals, &x509Request{
151- APIVersion: baseAPIVersion,
152 URL: AZURE_URL + "subscriptionId/services/hostedservices/S1?embed-detail=true",
153 Method: "GET",
154 })
155- // The third for S2's properties
156- c.Assert(len(record), Not(Equals), 2)
157- c.Check(record[2], DeepEquals, &x509Request{
158- APIVersion: baseAPIVersion,
159- URL: AZURE_URL + "subscriptionId/services/hostedservices/S2?embed-detail=true",
160- Method: "GET",
161- })
162-}
163-
164-func (suite *managementAPISuite) TestListInstancesFailsGettingServices(c *C) {
165- rigPreparedResponseDispatcher(
166- []DispatcherResponse{
167- {
168- response: &x509Response{
169- StatusCode: http.StatusUnauthorized,
170- },
171- },
172- },
173- )
174- api := makeAPI(c)
175- instances, err := api.ListInstances()
176- c.Check(instances, IsNil)
177- c.Assert(err, NotNil)
178- c.Assert(err.Error(), Equals, "GET request failed (401: Unauthorized)")
179 }
180
181 func (suite *managementAPISuite) TestListInstancesFailsGettingDetails(c *C) {
182- // First response is the list of services.
183- services := HostedServiceDescriptorList{
184- HostedServices: []HostedServiceDescriptor{
185- {ServiceName: "S1"},
186- },
187- }
188- servicesXML, err := services.Serialize()
189- c.Assert(err, IsNil)
190- servicesResponse := DispatcherResponse{
191- response: &x509Response{
192- Body: []byte(servicesXML),
193- StatusCode: http.StatusOK,
194- },
195- }
196- // Second response to the properties request is Not Found, to simulate a
197- // race perhaps.
198 propertiesS1Response := DispatcherResponse{
199 response: &x509Response{
200 StatusCode: http.StatusNotFound,
201 },
202 }
203 rigPreparedResponseDispatcher(
204- []DispatcherResponse{
205- servicesResponse,
206- propertiesS1Response,
207- },
208+ []DispatcherResponse{propertiesS1Response},
209 )
210 api := makeAPI(c)
211- instances, err := api.ListInstances()
212+ request := &ListInstancesRequest{ServiceName: "SomeService"}
213+ instances, err := api.ListInstances(request)
214 c.Check(instances, IsNil)
215 c.Assert(err, NotNil)
216 c.Assert(err.Error(), Equals, "GET request failed (404: Not Found)")

Subscribers

People subscribed via source and target branches

to all changes: