Merge lp:~klyachin/gomaasapi/101-testserver-extensions into lp:gomaasapi

Proposed by Vladislav Klyachin
Status: Merged
Approved by: Vladislav Klyachin
Approved revision: 50
Merged at revision: 49
Proposed branch: lp:~klyachin/gomaasapi/101-testserver-extensions
Merge into: lp:gomaasapi
Diff against target: 401 lines (+288/-10)
2 files modified
testservice.go (+135/-10)
testservice_test.go (+153/-0)
To merge this branch: bzr merge lp:~klyachin/gomaasapi/101-testserver-extensions
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+214961@code.launchpad.net

Commit message

testservice: version/network/details support

These changes are for juju-core project testing. They include new API endpoints:

- /version/
  return capabilities, currently only networks-management
- /network/<name>/?op=list_connected_macs
  returns list of MAC addresses connected to a network
- /nodes/<system_id>/?op=details
  returns lshw XML as application/bson, the XML data should be added before with AddNodeDetails(systemId, xml) function

Now for API endpoint:
  /networks?node=system_id
TestService returns empty list if node is not found or no networks are connected to the node.
It panicked before.

https://codereview.appspot.com/86070043/

R=dimitern, klyachin, rvb

Description of the change

testservice: version/network/details support

These changes are for juju-core project testing. They include new API endpoints:

- /version/
  return capabilities, currently only networks-management
- /network/<name>/?op=list_connected_macs
  returns list of MAC addresses connected to a network
- /nodes/<system_id>/?op=details
  returns lshw XML as application/bson, the XML data should be added before with AddNodeDetails(systemId, xml) function

Now for API endpoint:
  /networks?node=system_id
TestService returns empty list if node is not found or no networks are connected to the node.
It panicked before.

https://codereview.appspot.com/86070043/

To post a comment you must log in.
Revision history for this message
Vladislav Klyachin (klyachin) wrote :

Please take a look.

Revision history for this message
Vladislav Klyachin (klyachin) wrote :

Please take a look.

Revision history for this message
Vladislav Klyachin (klyachin) wrote :

Reviewers: mp+214961_code.launchpad.net,

Message:
Please take a look.

Description:
testservice: version/network/details support

These changes are for juju-core project testing. They include new API
endpoints:

- /version/
   return capabilities, currently only networks-management
- /network/<name>/?op=list_connected_macs
   returns list of MAC addresses connected to a network
- /nodes/<system_id>/?op=details
   returns lshw XML as application/bson, the XML data should be added
before with AddNodeDetails(systemId, xml) function

Now for API endpoint:
   /networks?node=system_id
TestService returns empty list if node is not found or no networks are
connected to the node.
It panicked before.

https://code.launchpad.net/~klyachin/gomaasapi/101-testserver-extensions/+merge/214961

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/86070043/

Affected files (+277, -6 lines):
   A [revision details]
   M testservice.go
   M testservice_test.go

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

LGTM with a couple of remarks.

https://codereview.appspot.com/86070043/diff/1/testservice.go
File testservice.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode482
testservice.go:482: // AddNodeDetails srores node details, expected in
XML format.
typo: stores

https://codereview.appspot.com/86070043/diff/1/testservice_test.go
File testservice_test.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode647
testservice_test.go:647: expectedResourceURI =
fmt.Sprintf("/api/%s/nodes/mysystemid/macs/aa%%3Abb%%3Acc%%3Add%%3Aee%%3Aff/",
apiVersion)
Probably better to express this as the url-escaped version of
'aa:bb:cc:dd:ee:ff'. Here and elsewhere.

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode669
testservice_test.go:669: c.Assert(err, IsNil)
This is a bit awkward, can we check the entire set instead of picking
the first node and testing that?

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode718
testservice_test.go:718: xmlText := `<?xml version="1.0"
standalone="yes" ?>
It's a detail but don't we have a equivalent to Python textwrap.dedent
to better format this?

https://codereview.appspot.com/86070043/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :
Download full text (3.6 KiB)

Looks almost there, but I have a few suggestions below:

https://codereview.appspot.com/86070043/diff/1/testservice.go
File testservice.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode279
testservice.go:279: func (server *TestServer)
ConnectNodeToNetworkWithMACAddress(systemId, name, macAddress string) {
s/name/networkName/ ?

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode282
testservice.go:282: panic("no node with given system id")
s/given/the given/ ?

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode284
testservice.go:284: _, hasNetwork := server.networks[name]
or:

if _, hasNetwork := server.networks[name]; !hasNetwork {
...
}

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode300
testservice.go:300: } else {
No need for that else block.

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode332
testservice.go:332: // Register handler for '/api/version/'.
... for '/api/<version>/version/'

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode494
testservice.go:494: attrs["lldp"] = []byte("<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n<lldp label=\"LLDP neighbors\"/>")
Can you define:

const lldpXML = `
<?xml version="1.0" encoding="UTF-8"?>
<lldp label="LLDP neighbors"/>
`

...and use it here? It will look better I think.

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode664
testservice.go:664: // networkListingConnectedMACSHandler handles
requests for '/api/<version>/networks/<network>/?op=list_connected_macs'
s/Listing/List/ ?

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode673
testservice.go:673: var convertedMacAddresses =
[]map[string]JSONObject{}
Or just convertedMacAddresses := []map[string]JSONObject{}

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode701
testservice.go:701: panic("only list_connected_macs operation
implemented")
"only list_connected_macs and default operations implemented" ?

(default: op=="")

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode708
testservice.go:708: if !hasNetworks {
I think you can skip this case and just leave the else part (Marshal
should work with empty slices just the same as with nil slices I hope).

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode723
testservice.go:723: // versionHandler handles requests for
'/api/version/'.
'/api/<version>/version/'

https://codereview.appspot.com/86070043/diff/1/testservice_test.go
File testservice_test.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode624
testservice_test.go:624: c.Check(err, IsNil)
Assert on errors, rather than Check, that way if it's not what you
expect the test case is halted immediately, rather than blowing up down
the line (see gocheck docs about Assert vs. Check).

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode627
testservice_test.go:627: c.Check(len(listNodes), Equals, 1)
c.Check(listNodes, HasLen, 1)

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode640
testservice_test.go:640: c.Check(len(macAddressSet), Equals, 1)...

Read more...

50. By Vladislav Klyachin

Made suggested changes

Revision history for this message
Vladislav Klyachin (klyachin) wrote :
Revision history for this message
Vladislav Klyachin (klyachin) wrote :

On 2014/04/09 15:19:48, rvb wrote:
> LGTM with a couple of remarks.

> https://codereview.appspot.com/86070043/diff/1/testservice.go
> File testservice.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice.go#newcode482
> testservice.go:482: // AddNodeDetails srores node details, expected in
XML
> format.
> typo: stores
Done.

> https://codereview.appspot.com/86070043/diff/1/testservice_test.go
> File testservice_test.go (right):

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode647
> testservice_test.go:647: expectedResourceURI =

fmt.Sprintf("/api/%s/nodes/mysystemid/macs/aa%%3Abb%%3Acc%%3Add%%3Aee%%3Aff/",
> apiVersion)
> Probably better to express this as the url-escaped version of
> 'aa:bb:cc:dd:ee:ff'. Here and elsewhere.
Done.

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode669
> testservice_test.go:669: c.Assert(err, IsNil)
> This is a bit awkward, can we check the entire set instead of picking
the first
> node and testing that?
The problem is that mac addresses can be in an arbitrary order.
Golang language spec explicitly defines maps as having undefined
ordering of keys.

https://codereview.appspot.com/86070043/diff/1/testservice_test.go#newcode718
> testservice_test.go:718: xmlText := `<?xml version="1.0"
standalone="yes" ?>
> It's a detail but don't we have a equivalent to Python textwrap.dedent
to better
> format this?
Didn't find dedent analogue in Go.
Moved text to a string constant outside of the function.

https://codereview.appspot.com/86070043/

Revision history for this message
Vladislav Klyachin (klyachin) wrote :

On 2014/04/09 15:58:23, dimitern wrote:
> Looks almost there, but I have a few suggestions below:

Thanks for the review, dimitern. All changes suggested were made.

https://codereview.appspot.com/86070043/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

On 2014/04/09 17:10:23, vladislav.klyachin wrote:
> On 2014/04/09 15:58:23, dimitern wrote:
> > Looks almost there, but I have a few suggestions below:
> >
> Thanks for the review, dimitern. All changes suggested were made.

Thanks, LGTM!

https://codereview.appspot.com/86070043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'testservice.go'
2--- testservice.go 2014-04-01 14:47:23 +0000
3+++ testservice.go 2014-04-09 17:04:10 +0000
4@@ -9,6 +9,7 @@
5 "encoding/json"
6 "fmt"
7 "io/ioutil"
8+ "labix.org/v2/mgo/bson"
9 "mime/multipart"
10 "net/http"
11 "net/http/httptest"
12@@ -66,6 +67,8 @@
13 networks map[string]MAASObject
14 networksPerNode map[string][]string
15 version string
16+ macAddressesPerNetwork map[string]map[string]JSONObject
17+ nodeDetails map[string]string
18 }
19
20 func getNodesEndpoint(version string) string {
21@@ -105,6 +108,23 @@
22 return fmt.Sprintf("/api/%s/networks/%s/", version, name)
23 }
24
25+func getNetworkURLRE(version string) *regexp.Regexp {
26+ reString := fmt.Sprintf("^/api/%s/networks/(.*)/$", regexp.QuoteMeta(version))
27+ return regexp.MustCompile(reString)
28+}
29+
30+func getMACAddressURL(version, systemId, macAddress string) string {
31+ return fmt.Sprintf("/api/%s/nodes/%s/macs/%s/", version, systemId, url.QueryEscape(macAddress))
32+}
33+
34+func getVersionURL(version string) string {
35+ return fmt.Sprintf("/api/%s/version/", version)
36+}
37+
38+func getVersionJSON() string {
39+ return `{"capabilities": ["networks-management"]}`
40+}
41+
42 // Clear clears all the fake data stored and recorded by the test server
43 // (nodes, recorded operations, etc.).
44 func (server *TestServer) Clear() {
45@@ -115,6 +135,8 @@
46 server.files = make(map[string]MAASObject)
47 server.networks = make(map[string]MAASObject)
48 server.networksPerNode = make(map[string][]string)
49+ server.macAddressesPerNetwork = make(map[string]map[string]JSONObject)
50+ server.nodeDetails = make(map[string]string)
51 }
52
53 // NodeOperations returns the map containing the list of the operations
54@@ -244,16 +266,45 @@
55 func (server *TestServer) ConnectNodeToNetwork(systemId, name string) {
56 _, hasNode := server.nodes[systemId]
57 if !hasNode {
58- panic("no node with given system id")
59+ panic("no node with the given system id")
60 }
61 _, hasNetwork := server.networks[name]
62 if !hasNetwork {
63- panic("no network with given name")
64+ panic("no network with the given name")
65 }
66 networkNames, _ := server.networksPerNode[systemId]
67 server.networksPerNode[systemId] = append(networkNames, name)
68 }
69
70+func (server *TestServer) ConnectNodeToNetworkWithMACAddress(systemId, networkName, macAddress string) {
71+ node, hasNode := server.nodes[systemId]
72+ if !hasNode {
73+ panic("no node with the given system id")
74+ }
75+ if _, hasNetwork := server.networks[networkName]; !hasNetwork {
76+ panic("no network with the given name")
77+ }
78+ networkNames, _ := server.networksPerNode[systemId]
79+ server.networksPerNode[systemId] = append(networkNames, networkName)
80+ attrs := make(map[string]interface{})
81+ attrs[resourceURI] = getMACAddressURL(server.version, systemId, macAddress)
82+ attrs["mac_address"] = macAddress
83+ array := []JSONObject{}
84+ if set, ok := node.GetMap()["macaddress_set"]; ok {
85+ var err error
86+ array, err = set.GetArray()
87+ if err != nil {
88+ panic(err)
89+ }
90+ }
91+ array = append(array, maasify(server.client, attrs))
92+ node.GetMap()["macaddress_set"] = JSONObject{value: array, client: server.client}
93+ if _, ok := server.macAddressesPerNetwork[networkName]; !ok {
94+ server.macAddressesPerNetwork[networkName] = map[string]JSONObject{}
95+ }
96+ server.macAddressesPerNetwork[networkName][systemId] = maasify(server.client, attrs)
97+}
98+
99 // NewTestServer starts and returns a new MAAS test server. The caller should call Close when finished, to shut it down.
100 func NewTestServer(version string) *TestServer {
101 server := &TestServer{version: version}
102@@ -274,6 +325,11 @@
103 serveMux.HandleFunc(networksURL, func(w http.ResponseWriter, r *http.Request) {
104 networksHandler(server, w, r)
105 })
106+ versionURL := getVersionURL(server.version)
107+ // Register handler for '/api/<version>/version/'.
108+ serveMux.HandleFunc(versionURL, func(w http.ResponseWriter, r *http.Request) {
109+ versionHandler(server, w, r)
110+ })
111
112 newServer := httptest.NewServer(serveMux)
113 client, err := NewAnonymousClient(newServer.URL, "1.0")
114@@ -317,6 +373,9 @@
115 w.WriteHeader(http.StatusOK)
116 fmt.Fprint(w, marshalNode(node))
117 return
118+ } else if operation == "details" {
119+ nodeDetailsHandler(server, w, r, systemId)
120+ return
121 } else {
122 w.WriteHeader(http.StatusBadRequest)
123 return
124@@ -417,6 +476,32 @@
125 }
126 }
127
128+// AddNodeDetails stores node details, expected in XML format.
129+func (server *TestServer) AddNodeDetails(systemId, xmlText string) {
130+ _, hasNode := server.nodes[systemId]
131+ if !hasNode {
132+ panic("no node with the given system id")
133+ }
134+ server.nodeDetails[systemId] = xmlText
135+}
136+
137+const lldpXML = `
138+<?xml version="1.0" encoding="UTF-8"?>
139+<lldp label="LLDP neighbors"/>`
140+
141+// nodeDetailesHandler handles requests for '/api/<version>/nodes/<system_id>/?op=details'.
142+func nodeDetailsHandler(server *TestServer, w http.ResponseWriter, r *http.Request, systemId string) {
143+ attrs := make(map[string]interface{})
144+ attrs["lldp"] = lldpXML
145+ xmlText, _ := server.nodeDetails[systemId]
146+ attrs["lshw"] = []byte(xmlText)
147+ res, err := bson.Marshal(attrs)
148+ checkError(err)
149+ w.Header().Set("Content-Type", "application/bson")
150+ w.WriteHeader(http.StatusOK)
151+ fmt.Fprint(w, string(res))
152+}
153+
154 // filesHandler handles requests for '/api/<version>/files/*'.
155 func filesHandler(server *TestServer, w http.ResponseWriter, r *http.Request) {
156 values, err := url.ParseQuery(r.URL.RawQuery)
157@@ -577,6 +662,29 @@
158 w.WriteHeader(http.StatusOK)
159 }
160
161+// networkListConnectedMACSHandler handles requests for '/api/<version>/networks/<network>/?op=list_connected_macs'
162+func networkListConnectedMACSHandler(server *TestServer, w http.ResponseWriter, r *http.Request) {
163+ networkURLRE := getNetworkURLRE(server.version)
164+ networkURLREMatch := networkURLRE.FindStringSubmatch(r.URL.Path)
165+ if networkURLREMatch == nil {
166+ http.NotFoundHandler().ServeHTTP(w, r)
167+ return
168+ }
169+ networkName := networkURLREMatch[1]
170+ convertedMacAddresses := []map[string]JSONObject{}
171+ if macAddresses, ok := server.macAddressesPerNetwork[networkName]; ok {
172+ for _, macAddress := range macAddresses {
173+ m, err := macAddress.GetMap()
174+ checkError(err)
175+ convertedMacAddresses = append(convertedMacAddresses, m)
176+ }
177+ }
178+ res, err := json.Marshal(convertedMacAddresses)
179+ checkError(err)
180+ w.WriteHeader(http.StatusOK)
181+ fmt.Fprint(w, string(res))
182+}
183+
184 // networksHandler handles requests for '/api/<version>/networks/?node=system_id'.
185 func networksHandler(server *TestServer, w http.ResponseWriter, r *http.Request) {
186 if r.Method != "GET" {
187@@ -584,21 +692,38 @@
188 }
189 values, err := url.ParseQuery(r.URL.RawQuery)
190 checkError(err)
191+ op := values.Get("op")
192 systemId := values.Get("node")
193+ if op == "list_connected_macs" {
194+ networkListConnectedMACSHandler(server, w, r)
195+ return
196+ }
197+ if op != "" {
198+ panic("only list_connected_macs and default operations implemented")
199+ }
200 if systemId == "" {
201 panic("network missing associated node system id")
202 }
203- networkNames, hasNetworks := server.networksPerNode[systemId]
204- if !hasNetworks {
205- // TODO(gz): Should be an HTTP error not a panic
206- panic("no networks exists for the given node system id")
207- }
208- networks := make([]MAASObject, len(networkNames))
209- for i, networkName := range networkNames {
210- networks[i] = server.networks[networkName]
211+ networks := []MAASObject{}
212+ if networkNames, hasNetworks := server.networksPerNode[systemId]; hasNetworks {
213+ networks = make([]MAASObject, len(networkNames))
214+ for i, networkName := range networkNames {
215+ networks[i] = server.networks[networkName]
216+ }
217 }
218 res, err := json.Marshal(networks)
219 checkError(err)
220+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
221 w.WriteHeader(http.StatusOK)
222 fmt.Fprint(w, string(res))
223 }
224+
225+// versionHandler handles requests for '/api/<version>/version/'.
226+func versionHandler(server *TestServer, w http.ResponseWriter, r *http.Request) {
227+ if r.Method != "GET" {
228+ panic("only version GET operation implemented")
229+ }
230+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
231+ w.WriteHeader(http.StatusOK)
232+ fmt.Fprint(w, getVersionJSON())
233+}
234
235=== modified file 'testservice_test.go'
236--- testservice_test.go 2014-04-01 14:47:23 +0000
237+++ testservice_test.go 2014-04-09 17:04:10 +0000
238@@ -9,6 +9,7 @@
239 "encoding/json"
240 "fmt"
241 "io"
242+ "labix.org/v2/mgo/bson"
243 . "launchpad.net/gocheck"
244 "mime/multipart"
245 "net/http"
246@@ -595,3 +596,155 @@
247 c.Assert(err, IsNil)
248 c.Check(networkName, Equals, "mynetworkname")
249 }
250+
251+func (suite *TestMAASObjectSuite) TestGetNetworksNone(c *C) {
252+ nodeJSON := `{"system_id": "mysystemid"}`
253+ suite.TestMAASObject.TestServer.NewNode(nodeJSON)
254+
255+ networkMethod := suite.TestMAASObject.GetSubObject("networks")
256+ params := url.Values{"node": []string{"mysystemid"}}
257+ listNetworkObjects, err := networkMethod.CallGet("", params)
258+ c.Assert(err, IsNil)
259+
260+ networkJSONArray, err := listNetworkObjects.GetArray()
261+ c.Assert(err, IsNil)
262+ c.Check(networkJSONArray, HasLen, 0)
263+}
264+
265+func (suite *TestMAASObjectSuite) TestListNodesWithNetworks(c *C) {
266+ nodeJSON := `{"system_id": "mysystemid"}`
267+ suite.TestMAASObject.TestServer.NewNode(nodeJSON)
268+ networkJSON := `{"name": "mynetworkname"}`
269+ suite.TestMAASObject.TestServer.NewNetwork(networkJSON)
270+ suite.TestMAASObject.TestServer.ConnectNodeToNetworkWithMACAddress("mysystemid", "mynetworkname", "aa:bb:cc:dd:ee:ff")
271+
272+ nodeListing := suite.TestMAASObject.GetSubObject("nodes")
273+ listNodeObjects, err := nodeListing.CallGet("list", url.Values{})
274+ c.Assert(err, IsNil)
275+
276+ listNodes, err := listNodeObjects.GetArray()
277+ c.Assert(err, IsNil)
278+ c.Check(listNodes, HasLen, 1)
279+
280+ node, err := listNodes[0].GetMAASObject()
281+ c.Assert(err, IsNil)
282+ systemId, err := node.GetField("system_id")
283+ c.Assert(err, IsNil)
284+ c.Check(systemId, Equals, "mysystemid")
285+
286+ gotResourceURI, err := node.GetField(resourceURI)
287+ c.Assert(err, IsNil)
288+ apiVersion := suite.TestMAASObject.TestServer.version
289+ expectedResourceURI := fmt.Sprintf("/api/%s/nodes/mysystemid/", apiVersion)
290+ c.Check(gotResourceURI, Equals, expectedResourceURI)
291+
292+ macAddressSet, err := node.GetMap()["macaddress_set"].GetArray()
293+ c.Assert(err, IsNil)
294+ c.Check(macAddressSet, HasLen, 1)
295+
296+ macAddress, err := macAddressSet[0].GetMap()
297+ c.Assert(err, IsNil)
298+ macAddressString, err := macAddress["mac_address"].GetString()
299+ c.Check(macAddressString, Equals, "aa:bb:cc:dd:ee:ff")
300+
301+ gotResourceURI, err = macAddress[resourceURI].GetString()
302+ c.Assert(err, IsNil)
303+ expectedResourceURI = fmt.Sprintf("/api/%s/nodes/mysystemid/macs/%s/", apiVersion, url.QueryEscape("aa:bb:cc:dd:ee:ff"))
304+ c.Check(gotResourceURI, Equals, expectedResourceURI)
305+}
306+
307+func (suite *TestMAASObjectSuite) TestListNetworkConnectedMACAddresses(c *C) {
308+ suite.TestMAASObject.TestServer.NewNode(`{"system_id": "node_1"}`)
309+ suite.TestMAASObject.TestServer.NewNode(`{"system_id": "node_2"}`)
310+ suite.TestMAASObject.TestServer.NewNetwork(`{"name": "net_1"}`)
311+ suite.TestMAASObject.TestServer.NewNetwork(`{"name": "net_2"}`)
312+ suite.TestMAASObject.TestServer.ConnectNodeToNetworkWithMACAddress("node_2", "net_2", "aa:bb:cc:dd:ee:22")
313+ suite.TestMAASObject.TestServer.ConnectNodeToNetworkWithMACAddress("node_1", "net_1", "aa:bb:cc:dd:ee:11")
314+ suite.TestMAASObject.TestServer.ConnectNodeToNetworkWithMACAddress("node_2", "net_1", "aa:bb:cc:dd:ee:21")
315+ suite.TestMAASObject.TestServer.ConnectNodeToNetworkWithMACAddress("node_1", "net_2", "aa:bb:cc:dd:ee:12")
316+
317+ nodeListing := suite.TestMAASObject.GetSubObject("networks").GetSubObject("net_1")
318+ listNodeObjects, err := nodeListing.CallGet("list_connected_macs", url.Values{})
319+ c.Assert(err, IsNil)
320+
321+ listNodes, err := listNodeObjects.GetArray()
322+ c.Assert(err, IsNil)
323+ c.Check(listNodes, HasLen, 2)
324+
325+ node, err := listNodes[0].GetMAASObject()
326+ c.Assert(err, IsNil)
327+ macAddress, err := node.GetField("mac_address")
328+ c.Assert(err, IsNil)
329+ c.Check(macAddress == "aa:bb:cc:dd:ee:11" || macAddress == "aa:bb:cc:dd:ee:21", Equals, true)
330+ node1_idx := 0
331+ if macAddress == "aa:bb:cc:dd:ee:21" {
332+ node1_idx = 1
333+ }
334+
335+ node, err = listNodes[node1_idx].GetMAASObject()
336+ c.Assert(err, IsNil)
337+ macAddress, err = node.GetField("mac_address")
338+ c.Assert(err, IsNil)
339+ c.Check(macAddress, Equals, "aa:bb:cc:dd:ee:11")
340+ nodeResourceURI, err := node.GetField(resourceURI)
341+ c.Assert(err, IsNil)
342+ apiVersion := suite.TestMAASObject.TestServer.version
343+ expectedResourceURI := fmt.Sprintf("/api/%s/nodes/node_1/macs/%s/", apiVersion, url.QueryEscape("aa:bb:cc:dd:ee:11"))
344+ c.Check(nodeResourceURI, Equals, expectedResourceURI)
345+
346+ node, err = listNodes[1-node1_idx].GetMAASObject()
347+ c.Assert(err, IsNil)
348+ macAddress, err = node.GetField("mac_address")
349+ c.Assert(err, IsNil)
350+ c.Check(macAddress, Equals, "aa:bb:cc:dd:ee:21")
351+ nodeResourceURI, err = node.GetField(resourceURI)
352+ c.Assert(err, IsNil)
353+ expectedResourceURI = fmt.Sprintf("/api/%s/nodes/node_2/macs/%s/", apiVersion, url.QueryEscape("aa:bb:cc:dd:ee:21"))
354+ c.Check(nodeResourceURI, Equals, expectedResourceURI)
355+}
356+
357+func (suite *TestMAASObjectSuite) TestGetVersion(c *C) {
358+ networkMethod := suite.TestMAASObject.GetSubObject("version")
359+ params := url.Values{"node": []string{"mysystemid"}}
360+ versionObject, err := networkMethod.CallGet("", params)
361+ c.Assert(err, IsNil)
362+
363+ versionMap, err := versionObject.GetMap()
364+ c.Assert(err, IsNil)
365+ jsonArray, ok := versionMap["capabilities"]
366+ c.Check(ok, Equals, true)
367+ capArray, err := jsonArray.GetArray()
368+ for _, capJSONName := range capArray {
369+ capName, err := capJSONName.GetString()
370+ c.Assert(err, IsNil)
371+ c.Check(capName, Equals, "networks-management")
372+ }
373+}
374+
375+const nodeDetailsXML = `<?xml version="1.0" standalone="yes" ?>
376+<list>
377+<node id="node2" claimed="true" class="system" handle="DMI:0001">
378+ <description>Computer</description>
379+</node>
380+</list>`
381+
382+func (suite *TestMAASObjectSuite) TestNodeDetails(c *C) {
383+ nodeJSON := `{"system_id": "mysystemid"}`
384+ suite.TestMAASObject.TestServer.NewNode(nodeJSON)
385+ suite.TestMAASObject.TestServer.AddNodeDetails("mysystemid", nodeDetailsXML)
386+
387+ obj := suite.TestMAASObject.GetSubObject("nodes").GetSubObject("mysystemid")
388+ uri := obj.URI()
389+ result, err := obj.client.Get(uri, "details", nil)
390+ c.Assert(err, IsNil)
391+
392+ bsonObj := map[string]interface{}{}
393+ err = bson.Unmarshal(result, &bsonObj)
394+ c.Assert(err, IsNil)
395+
396+ _, ok := bsonObj["lldp"]
397+ c.Check(ok, Equals, true)
398+ gotXMLText, ok := bsonObj["lshw"]
399+ c.Check(ok, Equals, true)
400+ c.Check(string(gotXMLText.([]byte)), Equals, string(nodeDetailsXML))
401+}

Subscribers

People subscribed via source and target branches

to all changes: