Merge lp:~mfoord/gomaasapi/nodegroupsinterfaces into lp:gomaasapi

Proposed by Michael Foord
Status: Merged
Approved by: Michael Foord
Approved revision: 65
Merged at revision: 59
Proposed branch: lp:~mfoord/gomaasapi/nodegroupsinterfaces
Merge into: lp:gomaasapi
Diff against target: 220 lines (+136/-1)
2 files modified
testservice.go (+60/-1)
testservice_test.go (+76/-0)
To merge this branch: bzr merge lp:~mfoord/gomaasapi/nodegroupsinterfaces
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Dimiter Naydenov (community) Approve
Review via email: mp+245891@code.launchpad.net

Description of the change

Add nodegroups-interfaces endpoint for TestServer. Also fix bug in nodegroups listing when there are no nodegroups.

To post a comment you must log in.
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Great! Just a few trivial suggestions. I'd suggest asking for a second review from rvba or allenap.

review: Approve
65. By Michael Foord

Minor tweaks from review

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

Looks good. One question inline.

review: Approve

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-10-20 14:17:24 +0000
3+++ testservice.go 2015-01-09 10:04:33 +0000
4@@ -82,6 +82,9 @@
5 zones map[string]JSONObject
6 // bootImages is a map of nodegroup UUIDs to boot-image objects.
7 bootImages map[string][]JSONObject
8+ // nodegroupsInterfaces is a map of nodegroup UUIDs to interface
9+ // objects.
10+ nodegroupsInterfaces map[string][]JSONObject
11 }
12
13 func getNodesEndpoint(version string) string {
14@@ -150,6 +153,11 @@
15 return fmt.Sprintf("/api/%s/nodegroups/%s/", version, uuid)
16 }
17
18+func getNodegroupsInterfacesURLRE(version string) *regexp.Regexp {
19+ reString := fmt.Sprintf("^/api/%s/nodegroups/([^/]*)/interfaces/$", regexp.QuoteMeta(version))
20+ return regexp.MustCompile(reString)
21+}
22+
23 func getBootimagesURLRE(version string) *regexp.Regexp {
24 reString := fmt.Sprintf("^/api/%s/nodegroups/([^/]*)/boot-images/$", regexp.QuoteMeta(version))
25 return regexp.MustCompile(reString)
26@@ -175,6 +183,7 @@
27 server.macAddressesPerNetwork = make(map[string]map[string]JSONObject)
28 server.nodeDetails = make(map[string]string)
29 server.bootImages = make(map[string][]JSONObject)
30+ server.nodegroupsInterfaces = make(map[string][]JSONObject)
31 server.zones = make(map[string]JSONObject)
32 }
33
34@@ -363,6 +372,28 @@
35 return obj
36 }
37
38+// NewNodegroupInterface adds a nodegroup-interface, for the specified
39+// nodegroup, in the test MAAS server.
40+func (server *TestServer) NewNodegroupInterface(uuid, jsonText string) JSONObject {
41+ _, ok := server.bootImages[uuid]
42+ if !ok {
43+ panic("no nodegroup with the given UUID")
44+ }
45+ var attrs map[string]interface{}
46+ err := json.Unmarshal([]byte(jsonText), &attrs)
47+ checkError(err)
48+ requiredMembers := []string{"ip_range_high", "ip_range_low", "broadcast_ip", "static_ip_range_low", "static_ip_range_high", "name", "ip", "subnet_mask", "management", "interface"}
49+ for _, member := range requiredMembers {
50+ _, hasMember := attrs[member]
51+ if !hasMember {
52+ panic(fmt.Sprintf("The given map json string does not contain a required %q", member))
53+ }
54+ }
55+ obj := maasify(server.client, attrs)
56+ server.nodegroupsInterfaces[uuid] = append(server.nodegroupsInterfaces[uuid], obj)
57+ return obj
58+}
59+
60 func (server *TestServer) ConnectNodeToNetwork(systemId, name string) {
61 _, hasNode := server.nodes[systemId]
62 if !hasNode {
63@@ -465,6 +496,7 @@
64 serveMux.HandleFunc(nodegroupsURL, func(w http.ResponseWriter, r *http.Request) {
65 nodegroupsHandler(server, w, r)
66 })
67+
68 // Register handler for '/api/<version>/zones/*'.
69 zonesURL := getZonesEndpoint(server.version)
70 serveMux.HandleFunc(zonesURL, func(w http.ResponseWriter, r *http.Request) {
71@@ -1095,12 +1127,16 @@
72 op := values.Get("op")
73 bootimagesURLRE := getBootimagesURLRE(server.version)
74 bootimagesURLMatch := bootimagesURLRE.FindStringSubmatch(r.URL.Path)
75+ nodegroupsInterfacesURLRE := getNodegroupsInterfacesURLRE(server.version)
76+ nodegroupsInterfacesURLMatch := nodegroupsInterfacesURLRE.FindStringSubmatch(r.URL.Path)
77 nodegroupsURL := getNodegroupsEndpoint(server.version)
78 switch {
79 case r.URL.Path == nodegroupsURL:
80 nodegroupsTopLevelHandler(server, w, r, op)
81 case bootimagesURLMatch != nil:
82 bootimagesHandler(server, w, r, bootimagesURLMatch[1], op)
83+ case nodegroupsInterfacesURLMatch != nil:
84+ nodegroupsInterfacesHandler(server, w, r, nodegroupsInterfacesURLMatch[1], op)
85 default:
86 // Default handler: not found.
87 http.NotFoundHandler().ServeHTTP(w, r)
88@@ -1114,7 +1150,7 @@
89 return
90 }
91
92- var nodegroups []JSONObject
93+ nodegroups := []JSONObject{}
94 for uuid := range server.bootImages {
95 attrs := map[string]interface{}{
96 "uuid": uuid,
97@@ -1149,6 +1185,29 @@
98 fmt.Fprint(w, string(res))
99 }
100
101+// nodegroupsInterfacesHandler handles requests for '/api/<version>/nodegroups/<uuid>/interfaces/'
102+func nodegroupsInterfacesHandler(server *TestServer, w http.ResponseWriter, r *http.Request, nodegroupUUID, op string) {
103+ if r.Method != "GET" {
104+ w.WriteHeader(http.StatusBadRequest)
105+ return
106+ }
107+ _, ok := server.bootImages[nodegroupUUID]
108+ if !ok {
109+ http.NotFoundHandler().ServeHTTP(w, r)
110+ return
111+ }
112+
113+ interfaces, ok := server.nodegroupsInterfaces[nodegroupUUID]
114+ if !ok {
115+ // we already checked the nodegroup exists, so return an empty list
116+ interfaces = []JSONObject{}
117+ }
118+ res, err := json.Marshal(interfaces)
119+ checkError(err)
120+ w.WriteHeader(http.StatusOK)
121+ fmt.Fprint(w, string(res))
122+}
123+
124 // zonesHandler handles requests for '/api/<version>/zones/'.
125 func zonesHandler(server *TestServer, w http.ResponseWriter, r *http.Request) {
126 if r.Method != "GET" {
127
128=== modified file 'testservice_test.go'
129--- testservice_test.go 2014-10-20 14:17:24 +0000
130+++ testservice_test.go 2015-01-09 10:04:33 +0000
131@@ -66,6 +66,14 @@
132 c.Check(resp.StatusCode, Equals, http.StatusNotFound)
133 }
134
135+func (suite *TestServerSuite) TestHandlesNodegroupsInterfacesListingUnknownNodegroup(c *C) {
136+ invalidPath := fmt.Sprintf("/api/%s/nodegroups/unknown/interfaces/", suite.server.version)
137+ resp, err := http.Get(suite.server.Server.URL + invalidPath)
138+
139+ c.Check(err, IsNil)
140+ c.Check(resp.StatusCode, Equals, http.StatusNotFound)
141+}
142+
143 func (suite *TestServerSuite) TestNewNode(c *C) {
144 input := `{"system_id": "mysystemid"}`
145
146@@ -971,6 +979,74 @@
147 }
148 }
149
150+func (suite *TestMAASObjectSuite) TestListNodegroupsEmptyList(c *C) {
151+ nodegroupListing := suite.TestMAASObject.GetSubObject("nodegroups")
152+ result, err := nodegroupListing.CallGet("list", nil)
153+ c.Assert(err, IsNil)
154+
155+ nodegroups, err := result.GetArray()
156+ c.Assert(err, IsNil)
157+ c.Check(nodegroups, HasLen, 0)
158+}
159+
160+func (suite *TestMAASObjectSuite) TestListNodegroupInterfaces(c *C) {
161+ suite.TestMAASObject.TestServer.AddBootImage("uuid-0", `{"architecture": "arm64", "release": "trusty"}`)
162+ jsonText := `{
163+ "ip_range_high": "172.16.0.128",
164+ "ip_range_low": "172.16.0.2",
165+ "broadcast_ip": "172.16.0.255",
166+ "static_ip_range_low": "172.16.0.129",
167+ "name": "eth0",
168+ "ip": "172.16.0.2",
169+ "subnet_mask": "255.255.255.0",
170+ "management": 2,
171+ "static_ip_range_high": "172.16.0.255",
172+ "interface": "eth0"
173+ }`
174+
175+ suite.TestMAASObject.TestServer.NewNodegroupInterface("uuid-0", jsonText)
176+ nodegroupsInterfacesListing := suite.TestMAASObject.GetSubObject("nodegroups").GetSubObject("uuid-0").GetSubObject("interfaces")
177+ result, err := nodegroupsInterfacesListing.CallGet("list", nil)
178+ c.Assert(err, IsNil)
179+
180+ nodegroupsInterfaces, err := result.GetArray()
181+ c.Assert(err, IsNil)
182+ c.Check(nodegroupsInterfaces, HasLen, 1)
183+
184+ nodegroupsInterface, err := nodegroupsInterfaces[0].GetMap()
185+ c.Assert(err, IsNil)
186+
187+ checkMember := func(member, expectedValue string) {
188+ value, err := nodegroupsInterface[member].GetString()
189+ c.Assert(err, IsNil)
190+ c.Assert(value, Equals, expectedValue)
191+ }
192+ checkMember("ip_range_high", "172.16.0.128")
193+ checkMember("ip_range_low", "172.16.0.2")
194+ checkMember("broadcast_ip", "172.16.0.255")
195+ checkMember("static_ip_range_low", "172.16.0.129")
196+ checkMember("static_ip_range_high", "172.16.0.255")
197+ checkMember("name", "eth0")
198+ checkMember("ip", "172.16.0.2")
199+ checkMember("subnet_mask", "255.255.255.0")
200+ checkMember("interface", "eth0")
201+
202+ value, err := nodegroupsInterface["management"].GetFloat64()
203+ c.Assert(err, IsNil)
204+ c.Assert(value, Equals, 2.0)
205+}
206+
207+func (suite *TestMAASObjectSuite) TestListNodegroupsInterfacesEmptyList(c *C) {
208+ suite.TestMAASObject.TestServer.AddBootImage("uuid-0", `{"architecture": "arm64", "release": "trusty"}`)
209+ nodegroupsInterfacesListing := suite.TestMAASObject.GetSubObject("nodegroups").GetSubObject("uuid-0").GetSubObject("interfaces")
210+ result, err := nodegroupsInterfacesListing.CallGet("list", nil)
211+ c.Assert(err, IsNil)
212+
213+ interfaces, err := result.GetArray()
214+ c.Assert(err, IsNil)
215+ c.Check(interfaces, HasLen, 0)
216+}
217+
218 func (suite *TestMAASObjectSuite) TestListBootImages(c *C) {
219 suite.TestMAASObject.TestServer.AddBootImage("uuid-0", `{"architecture": "arm64", "release": "trusty"}`)
220 suite.TestMAASObject.TestServer.AddBootImage("uuid-1", `{"architecture": "amd64", "release": "precise"}`)

Subscribers

People subscribed via source and target branches

to all changes: