handler.go 19.2 KB
Newer Older
Stefan Dähling's avatar
Stefan Dähling committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
Copyright 2020 Institute for Automation of Complex Power Systems,
E.ON Energy Research Center, RWTH Aachen University

This project is licensed under either of
- Apache License, Version 2.0
- MIT License
at your option.

Apache License, Version 2.0:

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

MIT License:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// handler for http requests

package ams

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"strconv"

	"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/common/httpreply"
	"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/schemas"
Stefan Dähling's avatar
Stefan Dähling committed
58
	"github.com/gorilla/mux"
Stefan Dähling's avatar
Stefan Dähling committed
59
60
)

Stefan Dähling's avatar
Stefan Dähling committed
61
// handleAlive is the handler for requests to path /api/alive
Stefan Dähling's avatar
Stefan Dähling committed
62
63
64
65
func (ams *AMS) handleAlive(w http.ResponseWriter, r *http.Request) {
	var httpErr error
	httpErr = httpreply.Alive(w, nil)
	ams.logErrors(r.URL.Path, nil, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
66
67
68
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
69
// handleCloneMAP is the handler for requests to path /api/clonemap
Stefan Dähling's avatar
Stefan Dähling committed
70
71
72
73
74
func (ams *AMS) handleCloneMAP(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	// return info about running clonemap instance
	var cmapInfo schemas.CloneMAP
	cmapInfo, cmapErr = ams.getCloneMAPInfo()
75
76
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
77
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
78
79
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
80
	httpErr = httpreply.Resource(w, cmapInfo, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
81
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
82
83
84
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
85
86
87
88
89
// handleGetMAS is the handler for get requests to path /api/clonemap/mas
func (ams *AMS) handleGetMAS(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	var mass []schemas.MASInfoShort
	mass, cmapErr = ams.getMASsShort()
90
91
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
92
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
93
94
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
95
	httpErr = httpreply.Resource(w, mass, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
96
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
97
98
99
100
101
102
103
104
105
	return
}

// handlePostMAS is the handler for post requests to path /api/clonemap/mas
func (ams *AMS) handlePostMAS(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	// create new MAS
	var body []byte
	body, cmapErr = ioutil.ReadAll(r.Body)
Stefan Dähling's avatar
Stefan Dähling committed
106
	if cmapErr != nil {
Stefan Dähling's avatar
Stefan Dähling committed
107
		httpErr = httpreply.InvalidBodyError(w)
Stefan Dähling's avatar
Stefan Dähling committed
108
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
109
		return
Stefan Dähling's avatar
Stefan Dähling committed
110
	}
Stefan Dähling's avatar
Stefan Dähling committed
111
112
113
114
	var masSpec schemas.MASSpec
	cmapErr = json.Unmarshal(body, &masSpec)
	if cmapErr != nil {
		httpErr = httpreply.JSONUnmarshalError(w)
Stefan Dähling's avatar
Stefan Dähling committed
115
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
116
117
118
119
120
		return
	}
	cmapErr = ams.createMAS(masSpec)
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
121
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
122
123
124
		return
	}
	httpErr = httpreply.Created(w, cmapErr, "text/plain", []byte("Ressource Created"))
Stefan Dähling's avatar
Stefan Dähling committed
125
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
126
127
128
	return
}

129
// handleGetMASID is the handler for get requests to path /api/clonemap/mas/{masid}
Stefan Dähling's avatar
Stefan Dähling committed
130
131
132
133
func (ams *AMS) handleGetMASID(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
Stefan Dähling's avatar
Stefan Dähling committed
134
	if cmapErr != nil {
135
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
136
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
137
		return
Stefan Dähling's avatar
Stefan Dähling committed
138
	}
Stefan Dähling's avatar
Stefan Dähling committed
139
140
141
	// return long information about specified MAS
	var masInfo schemas.MASInfo
	masInfo, cmapErr = ams.getMASInfo(masID)
142
143
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
144
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
145
146
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
147
	httpErr = httpreply.Resource(w, masInfo, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
148
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
149
	return
Stefan Dähling's avatar
Stefan Dähling committed
150
151
}

152
// handleDeleteMASID is the handler for delete requests to path /api/clonemap/mas/{masid}
Stefan Dähling's avatar
Stefan Dähling committed
153
154
155
156
157
func (ams *AMS) handleDeleteMASID(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
158
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
159
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
160
		return
Stefan Dähling's avatar
Stefan Dähling committed
161
	}
Stefan Dähling's avatar
Stefan Dähling committed
162
163
	// delete specified MAS
	cmapErr = ams.removeMAS(masID)
164
165
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
166
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
167
168
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
169
	httpErr = httpreply.Deleted(w, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
170
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
171
172
173
174
175
176
177
178
179
180
181
	return
}

// handleGetMASName is the handler for get requests to path /api/clonemap/mas/name/{name}
func (ams *AMS) handleGetMASName(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	name := vars["name"]
	// search for MAS with matching name
	var ids []int
	ids, cmapErr = ams.getMASByName(name)
182
183
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
184
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
185
186
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
187
	httpErr = httpreply.Resource(w, ids, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
188
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
189
190
191
	return
}

192
// handleGetAgents is the handler for get requests to path /api/clonemap/mas/{masid}/agents
Stefan Dähling's avatar
Stefan Dähling committed
193
194
195
196
197
func (ams *AMS) handleGetAgents(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
198
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
199
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
200
		return
201
	}
Stefan Dähling's avatar
Stefan Dähling committed
202
203
204
	// return short information of all agents in specified MAS
	var agents schemas.Agents
	agents, cmapErr = ams.getAgents(masID)
205
206
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
207
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
208
209
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
210
	httpErr = httpreply.Resource(w, agents, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
211
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
212
213
214
	return
}

215
// handlePostAgent is the handler for post requests to path /api/clonemap/mas/{masid}/agents
Stefan Dähling's avatar
Stefan Dähling committed
216
217
218
219
220
func (ams *AMS) handlePostAgent(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
221
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
222
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
223
		return
Stefan Dähling's avatar
Stefan Dähling committed
224
	}
Stefan Dähling's avatar
Stefan Dähling committed
225
226
227
228
229
	// create new agent in MAS
	var body []byte
	body, cmapErr = ioutil.ReadAll(r.Body)
	if cmapErr != nil {
		httpErr = httpreply.InvalidBodyError(w)
Stefan Dähling's avatar
Stefan Dähling committed
230
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
231
232
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
233
234
	var imgroupSpecs []schemas.ImageGroupSpec
	cmapErr = json.Unmarshal(body, &imgroupSpecs)
Stefan Dähling's avatar
Stefan Dähling committed
235
236
	if cmapErr != nil {
		httpErr = httpreply.JSONUnmarshalError(w)
Stefan Dähling's avatar
Stefan Dähling committed
237
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
238
239
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
240
	cmapErr = ams.createAgents(masID, imgroupSpecs)
241
242
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
243
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
244
245
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
246
	httpErr = httpreply.Created(w, cmapErr, "text/plain", []byte("Ressource Created"))
Stefan Dähling's avatar
Stefan Dähling committed
247
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
248
249
250
	return
}

251
252
// handleGetAgentID is the handler for get requests to path
// /api/clonemap/mas/{masid}/agents/{agentid}
Stefan Dähling's avatar
Stefan Dähling committed
253
254
255
256
func (ams *AMS) handleGetAgentID(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	masID, agentID, cmapErr := getAgentID(r)
	if cmapErr != nil {
257
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
258
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
259
		return
Stefan Dähling's avatar
Stefan Dähling committed
260
	}
Stefan Dähling's avatar
Stefan Dähling committed
261
262
	var agentInfo schemas.AgentInfo
	agentInfo, cmapErr = ams.getAgentInfo(masID, agentID)
263
264
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
265
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
266
267
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
268
	httpErr = httpreply.Resource(w, agentInfo, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
269
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
270
271
272
	return
}

273
274
// handleDeleteAgentID is the handler for delete requests to path
// /api/clonemap/mas/{masid}/agents/{agentid}
Stefan Dähling's avatar
Stefan Dähling committed
275
276
277
278
func (ams *AMS) handleDeleteAgentID(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	masID, agentID, cmapErr := getAgentID(r)
	if cmapErr != nil {
279
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
280
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
281
282
283
284
		return
	}
	// delete specified agent
	cmapErr = ams.removeAgent(masID, agentID)
285
286
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
287
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
288
289
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
290
	httpErr = httpreply.Deleted(w, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
291
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
292
293
294
295
	return
}

// handleGetAgentAddress is the handler for get requests to path
296
// /api/clonemap/mas/{masid}/agents/{agentid}/address
Stefan Dähling's avatar
Stefan Dähling committed
297
298
299
300
func (ams *AMS) handleGetAgentAddress(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	masID, agentID, cmapErr := getAgentID(r)
	if cmapErr != nil {
301
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
302
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
303
304
305
306
307
		return
	}
	// return address of specified agent
	var agentAddr schemas.Address
	agentAddr, cmapErr = ams.getAgentAddress(masID, agentID)
Stefan Dähling's avatar
Stefan Dähling committed
308
309
310
311
312
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
313
	httpErr = httpreply.Resource(w, agentAddr, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
314
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
315
316
317
318
	return
}

// handlePutAgentAddress is the handler for put requests to path
319
// /api/clonemap/mas/{masid}/agents/{agentid}/address
Stefan Dähling's avatar
Stefan Dähling committed
320
321
322
323
func (ams *AMS) handlePutAgentAddress(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	masID, agentID, cmapErr := getAgentID(r)
	if cmapErr != nil {
324
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
325
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
326
327
328
329
330
331
332
		return
	}
	// update address of specified agent
	var body []byte
	body, cmapErr = ioutil.ReadAll(r.Body)
	if cmapErr != nil {
		httpErr = httpreply.InvalidBodyError(w)
Stefan Dähling's avatar
Stefan Dähling committed
333
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
334
335
336
337
338
339
		return
	}
	var agentAddr schemas.Address
	cmapErr = json.Unmarshal(body, &agentAddr)
	if cmapErr != nil {
		httpErr = httpreply.JSONUnmarshalError(w)
Stefan Dähling's avatar
Stefan Dähling committed
340
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
341
		return
Stefan Dähling's avatar
Stefan Dähling committed
342
	}
Stefan Dähling's avatar
Stefan Dähling committed
343
	cmapErr = ams.updateAgentAddress(masID, agentID, agentAddr)
344
345
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
346
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
347
348
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
349
	httpErr = httpreply.Updated(w, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
350
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
351
352
353
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
354
// handlePutAgentCustom is the put handler for requests to path
355
// /api/clonemap/mas/{masid}/agents/{agentid}/custom
Stefan Dähling's avatar
Stefan Dähling committed
356
357
358
359
func (ams *AMS) handlePutAgentCustom(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	masID, agentID, cmapErr := getAgentID(r)
	if cmapErr != nil {
360
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
361
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
362
		return
363
	}
Stefan Dähling's avatar
Stefan Dähling committed
364
365
366
367
368
	// update custom of specified agent
	var body []byte
	body, cmapErr = ioutil.ReadAll(r.Body)
	if cmapErr != nil {
		httpErr = httpreply.InvalidBodyError(w)
Stefan Dähling's avatar
Stefan Dähling committed
369
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
370
371
372
373
		return
	}
	custom := string(body)
	cmapErr = ams.updateAgentCustom(masID, agentID, custom)
374
375
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
376
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
377
378
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
379
	httpErr = httpreply.Updated(w, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
380
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
381
382
383
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
384
385
386
387
388
389
390
// handleGetAgentName is the handler for get requests to path
// /api/clonemap/mas/{masid}/agents/name/{name}
func (ams *AMS) handleGetAgentName(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
391
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
392
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
393
		return
394
	}
Stefan Dähling's avatar
Stefan Dähling committed
395
396
397
398
	name := vars["name"]
	// search for agents with matching name
	var ids []int
	ids, cmapErr = ams.getAgentsByName(masID, name)
399
400
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
401
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
402
403
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
404
	httpErr = httpreply.Resource(w, ids, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
405
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
406
407
408
	return
}

409
// handleGetAgencies is the handler for get requests to path /api/cloumap/mas/{masid}/agencies
Stefan Dähling's avatar
Stefan Dähling committed
410
411
412
413
414
func (ams *AMS) handleGetAgencies(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
415
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
416
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
417
		return
Stefan Dähling's avatar
Stefan Dähling committed
418
	}
Stefan Dähling's avatar
Stefan Dähling committed
419
420
421
	// return information of specified agency
	var agencies schemas.Agencies
	agencies, cmapErr = ams.getAgencies(masID)
422
423
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
424
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
425
426
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
427
	httpErr = httpreply.Resource(w, agencies, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
428
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
429
430
431
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
432
// handleGetAgencyID is the handler for get requests to path
433
// /api/clonemap/mas/{masid}/imgroup/{imid}/agencies/{agencyid}
Stefan Dähling's avatar
Stefan Dähling committed
434
435
436
437
438
func (ams *AMS) handleGetAgencyID(w http.ResponseWriter, r *http.Request) {
	var cmapErr, httpErr error
	vars := mux.Vars(r)
	masID, cmapErr := strconv.Atoi(vars["masid"])
	if cmapErr != nil {
439
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
440
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
441
		return
442
	}
Stefan Dähling's avatar
Stefan Dähling committed
443
444
	imID, cmapErr := strconv.Atoi(vars["imid"])
	if cmapErr != nil {
445
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
446
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
447
448
449
450
		return
	}
	agencyID, cmapErr := strconv.Atoi(vars["agencyid"])
	if cmapErr != nil {
451
		httpErr = httpreply.NotFoundError(w)
Stefan Dähling's avatar
Stefan Dähling committed
452
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
Stefan Dähling's avatar
Stefan Dähling committed
453
454
455
456
		return
	}
	var agencySpec schemas.AgencyInfoFull
	agencySpec, cmapErr = ams.getAgencyInfoFull(masID, imID, agencyID)
457
458
	if cmapErr != nil {
		httpErr = httpreply.CMAPError(w, cmapErr.Error())
Stefan Dähling's avatar
Stefan Dähling committed
459
		ams.logErrors(r.URL.Path, cmapErr, httpErr)
460
461
		return
	}
Stefan Dähling's avatar
Stefan Dähling committed
462
	httpErr = httpreply.Resource(w, agencySpec, cmapErr)
Stefan Dähling's avatar
Stefan Dähling committed
463
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
464
465
	return
}
Stefan Dähling's avatar
Stefan Dähling committed
466

Stefan Dähling's avatar
Stefan Dähling committed
467
468
469
470
471
472
473
474
// methodNotAllowed is the default handler for valid paths but invalid methods
func (ams *AMS) methodNotAllowed(w http.ResponseWriter, r *http.Request) {
	httpErr := httpreply.MethodNotAllowed(w)
	cmapErr := errors.New("Error: Method not allowed on path " + r.URL.Path)
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
475
476
477
478
479
480
481
482
// resourceNotFound is the default handler for invalid paths
func (ams *AMS) resourceNotFound(w http.ResponseWriter, r *http.Request) {
	httpErr := httpreply.NotFoundError(w)
	cmapErr := errors.New("Resource not found")
	ams.logErrors(r.URL.Path, cmapErr, httpErr)
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
483
484
485
486
487
488
489
490
491
492
493
// logErrors logs errors if any
func (ams *AMS) logErrors(path string, cmapErr error, httpErr error) {
	if cmapErr != nil {
		ams.logError.Println(path, cmapErr)
	}
	if httpErr != nil {
		ams.logError.Println(path, httpErr)
	}
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
494
495
496
497
498
499
500
501
502
503
504
505
506
507
// getAgentID returns the masID and agentID from the path
func getAgentID(r *http.Request) (masID int, agentID int, err error) {
	vars := mux.Vars(r)
	masID, err = strconv.Atoi(vars["masid"])
	if err != nil {
		return
	}
	agentID, err = strconv.Atoi(vars["agentid"])
	if err != nil {
		return
	}
	return
}

Stefan Dähling's avatar
Stefan Dähling committed
508
509
510
511
512
513
514
515
// loggingMiddleware logs request before calling final handler
func (ams *AMS) loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ams.logInfo.Println("Received Request: ", r.Method, " ", r.URL.EscapedPath())
		next.ServeHTTP(w, r)
	})
}

Stefan Dähling's avatar
Stefan Dähling committed
516
517
518
519
520
// server creates the ams server
func (ams *AMS) server(port int) (serv *http.Server) {
	r := mux.NewRouter()
	// r.HandleFunc("/api/", ams.handleAPI)
	s := r.PathPrefix("/api").Subrouter()
Stefan Dähling's avatar
Stefan Dähling committed
521
522
523
524
525
526
527
528
	s.Path("/alive").Methods("GET").HandlerFunc(ams.handleAlive)
	s.Path("/alive").Methods("POST", "PUT", "DELETE").HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap").Methods("GET").HandlerFunc(ams.handleCloneMAP)
	s.Path("/clonemap").Methods("POST", "PUT", "DELETE").HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas").Methods("GET").HandlerFunc(ams.handleGetMAS)
	s.Path("/clonemap/mas").Methods("POST").HandlerFunc(ams.handlePostMAS)
	s.Path("/clonemap/mas").Methods("PUT", "DELETE").HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}").Methods("GET").HandlerFunc(ams.handleGetMASID)
Stefan Dähling's avatar
Stefan Dähling committed
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
	s.Path("/clonemap/mas/{masid}").Methods("DELETE").HandlerFunc(ams.handleDeleteMASID)
	s.Path("/clonemap/mas/{masid}").Methods("PUT", "POST").HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/name/{name}").Methods("GET").HandlerFunc(ams.handleGetMASName)
	s.Path("/clonemap/mas/name/{name}").Methods("PUT", "POST", "DELETE").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agents").Methods("GET").HandlerFunc(ams.handleGetAgents)
	s.Path("/clonemap/mas/{masid}/agents").Methods("POST").HandlerFunc(ams.handlePostAgent)
	s.Path("/clonemap/mas/{masid}/agents").Methods("PUT", "DELETE").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}").Methods("GET").
		HandlerFunc(ams.handleGetAgentID)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}").Methods("DELETE").
		HandlerFunc(ams.handleDeleteAgentID)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}").Methods("PUT", "POST").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}/address").Methods("GET").
		HandlerFunc(ams.handleGetAgentAddress)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}/address").Methods("PUT").
		HandlerFunc(ams.handlePutAgentAddress)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}/address").Methods("DELETE", "POST").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}/custom").Methods("PUT").
		HandlerFunc(ams.handlePutAgentCustom)
	s.Path("/clonemap/mas/{masid}/agents/{agentid}/custom").Methods("DELETE", "POST", "GET").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agents/name/{name}").Methods("GET").
Stefan Dähling's avatar
Stefan Dähling committed
555
		HandlerFunc(ams.handleGetAgentName)
Stefan Dähling's avatar
Stefan Dähling committed
556
557
558
559
560
	s.Path("/clonemap/mas/{masid}/agents/name/{name}").Methods("DELETE", "POST", "PUT").
		HandlerFunc(ams.methodNotAllowed)
	s.Path("/clonemap/mas/{masid}/agencies").Methods("GET").HandlerFunc(ams.handleGetAgencies)
	s.Path("/clonemap/mas/{masid}/agencies").Methods("PUT", "DELETE", "POST").
		HandlerFunc(ams.methodNotAllowed)
Stefan Dähling's avatar
fix    
Stefan Dähling committed
561
	s.Path("/clonemap/mas/{masid}/imgroup/{imid}/agency/{agencyid}").Methods("GET").
Stefan Dähling's avatar
Stefan Dähling committed
562
		HandlerFunc(ams.handleGetAgencyID)
Stefan Dähling's avatar
fix    
Stefan Dähling committed
563
	s.Path("/clonemap/mas/{masid}/imgroup/{imid}/agency/{agencyid}").
Stefan Dähling's avatar
Stefan Dähling committed
564
565
		Methods("PUT", "DELETE", "POST").HandlerFunc(ams.methodNotAllowed)
	s.PathPrefix("").HandlerFunc(ams.resourceNotFound)
Stefan Dähling's avatar
Stefan Dähling committed
566
	s.Use(ams.loggingMiddleware)
Stefan Dähling's avatar
Stefan Dähling committed
567
568
569
	serv = &http.Server{
		Addr:    ":" + strconv.Itoa(port),
		Handler: r,
Stefan Dähling's avatar
Stefan Dähling committed
570
	}
Stefan Dähling's avatar
Stefan Dähling committed
571
572
573
574
575
576
577
	return
}

// listen opens a http server listening and serving request
func (ams *AMS) listen(serv *http.Server) (err error) {
	ams.logInfo.Println("AMS listening on " + serv.Addr)
	err = serv.ListenAndServe()
Stefan Dähling's avatar
Stefan Dähling committed
578
579
	return
}