c3d471c57f71b128f5fc0d268fc2074df0f7a6b7
[releng.git] / utils / test / testapi / opnfv_testapi / resources / scenario_handlers.py
1 import functools
2
3 from opnfv_testapi.resources import handlers
4 import opnfv_testapi.resources.scenario_models as models
5 from opnfv_testapi.tornado_swagger import swagger
6
7
8 class GenericScenarioHandler(handlers.GenericApiHandler):
9     def __init__(self, application, request, **kwargs):
10         super(GenericScenarioHandler, self).__init__(application,
11                                                      request,
12                                                      **kwargs)
13         self.table = self.db_scenarios
14         self.table_cls = models.Scenario
15
16     def set_query(self, locators):
17         query = dict()
18         elem_query = dict()
19         for k, v in locators.iteritems():
20             if k == 'scenario':
21                 query['name'] = v
22             elif k == 'installer':
23                 elem_query["installer"] = v
24             elif k == 'version':
25                 elem_query["versions.version"] = v
26             elif k == 'project':
27                 elem_query["versions.projects.project"] = v
28             else:
29                 query[k] = v
30         if elem_query:
31             query['installers'] = {'$elemMatch': elem_query}
32         return query
33
34
35 class ScenariosCLHandler(GenericScenarioHandler):
36     @swagger.operation(nickname="queryScenarios")
37     def get(self):
38         """
39             @description: Retrieve scenario(s).
40             @notes: Retrieve scenario(s)
41                 Available filters for this request are :
42                  - name : scenario name
43
44                 GET /scenarios?name=scenario_1
45             @param name: scenario name
46             @type name: L{string}
47             @in name: query
48             @required name: False
49             @param installer: installer type
50             @type installer: L{string}
51             @in installer: query
52             @required installer: False
53             @param version: version
54             @type version: L{string}
55             @in version: query
56             @required version: False
57             @param project: project name
58             @type project: L{string}
59             @in project: query
60             @required project: False
61             @return 200: all scenarios satisfy queries,
62                          empty list if no scenario is found
63             @rtype: L{Scenarios}
64         """
65
66         def _set_query():
67             query = dict()
68             elem_query = dict()
69             for k in self.request.query_arguments.keys():
70                 v = self.get_query_argument(k)
71                 if k == 'installer':
72                     elem_query["installer"] = v
73                 elif k == 'version':
74                     elem_query["versions.version"] = v
75                 elif k == 'project':
76                     elem_query["versions.projects.project"] = v
77                 else:
78                     query[k] = v
79             if elem_query:
80                 query['installers'] = {'$elemMatch': elem_query}
81             return query
82
83         self._list(query=_set_query())
84
85     @swagger.operation(nickname="createScenario")
86     def post(self):
87         """
88             @description: create a new scenario by name
89             @param body: scenario to be created
90             @type body: L{ScenarioCreateRequest}
91             @in body: body
92             @rtype: L{CreateResponse}
93             @return 200: scenario is created.
94             @raise 403: scenario already exists
95             @raise 400:  body or name not provided
96         """
97         def query():
98             return {'name': self.json_args.get('name')}
99         miss_fields = ['name']
100         self._create(miss_fields=miss_fields, query=query)
101
102
103 class ScenarioGURHandler(GenericScenarioHandler):
104     @swagger.operation(nickname='getScenarioByName')
105     def get(self, name):
106         """
107             @description: get a single scenario by name
108             @rtype: L{Scenario}
109             @return 200: scenario exist
110             @raise 404: scenario not exist
111         """
112         self._get_one(query={'name': name})
113         pass
114
115     def put(self, name):
116         pass
117
118     @swagger.operation(nickname="deleteScenarioByName")
119     def delete(self, name):
120         """
121         @description: delete a scenario by name
122         @return 200: delete success
123         @raise 404: scenario not exist:
124         """
125         self._delete(query={'name': name})
126
127
128 class ScenarioUpdater(object):
129     def __init__(self, data, body=None,
130                  installer=None, version=None, project=None):
131         self.data = data
132         self.body = body
133         self.installer = installer
134         self.version = version
135         self.project = project
136
137     def update(self, item, action):
138         updates = {
139             ('scores', 'post'): self._update_requests_add_score,
140             ('trust_indicators', 'post'): self._update_requests_add_ti,
141             ('customs', 'post'): self._update_requests_add_customs,
142             ('customs', 'put'): self._update_requests_update_customs,
143             ('customs', 'delete'): self._update_requests_delete_customs,
144         }
145         updates[(item, action)](self.data)
146
147         return self.data.format()
148
149     def iter_installers(xstep):
150         @functools.wraps(xstep)
151         def magic(self, data):
152             [xstep(self, installer)
153              for installer in self._filter_installers(data.installers)]
154         return magic
155
156     def iter_versions(xstep):
157         @functools.wraps(xstep)
158         def magic(self, installer):
159             [xstep(self, version)
160              for version in (self._filter_versions(installer.versions))]
161         return magic
162
163     def iter_projects(xstep):
164         @functools.wraps(xstep)
165         def magic(self, version):
166             [xstep(self, project)
167              for project in (self._filter_projects(version.projects))]
168         return magic
169
170     @iter_installers
171     @iter_versions
172     @iter_projects
173     def _update_requests_add_score(self, project):
174         project.scores.append(
175             models.ScenarioScore.from_dict(self.body))
176
177     @iter_installers
178     @iter_versions
179     @iter_projects
180     def _update_requests_add_ti(self, project):
181         project.trust_indicators.append(
182             models.ScenarioTI.from_dict(self.body))
183
184     @iter_installers
185     @iter_versions
186     @iter_projects
187     def _update_requests_add_customs(self, project):
188         project.customs = list(set(project.customs + self.body))
189
190     @iter_installers
191     @iter_versions
192     @iter_projects
193     def _update_requests_update_customs(self, project):
194         project.customs = list(set(self.body))
195
196     @iter_installers
197     @iter_versions
198     @iter_projects
199     def _update_requests_delete_customs(self, project):
200         project.customs = filter(
201             lambda f: f not in self.body,
202             project.customs)
203
204     def _filter_installers(self, installers):
205         return self._filter('installer', installers)
206
207     def _filter_versions(self, versions):
208         return self._filter('version', versions)
209
210     def _filter_projects(self, projects):
211         return self._filter('project', projects)
212
213     def _filter(self, item, items):
214         return filter(
215             lambda f: getattr(f, item) == getattr(self, item),
216             items)
217
218
219 class GenericScenarioUpdateHandler(GenericScenarioHandler):
220     def __init__(self, application, request, **kwargs):
221         super(GenericScenarioUpdateHandler, self).__init__(application,
222                                                            request,
223                                                            **kwargs)
224         self.installer = None
225         self.version = None
226         self.project = None
227         self.item = None
228         self.action = None
229
230     def do_update(self, item, action, locators):
231         self.item = item
232         self.action = action
233         for k, v in locators.iteritems():
234             if not v:
235                 v = self.get_query_argument(k)
236                 setattr(self, k, v)
237                 locators[k] = v
238         self.pure_update(query=self.set_query(locators=locators))
239         self.finish_request()
240
241     def _update_requests(self, data):
242         return ScenarioUpdater(data,
243                                self.json_args,
244                                self.installer,
245                                self.version,
246                                self.project).update(self.item, self.action)
247
248
249 class ScenarioScoresHandler(GenericScenarioUpdateHandler):
250     @swagger.operation(nickname="addScoreRecord")
251     def post(self, scenario):
252         """
253         @description: add a new score record
254         @notes: add a new score record to a project
255             POST /api/v1/scenarios/<scenario_name>/scores? \
256                 installer=<installer_name>& \
257                 version=<version_name>& \
258                 project=<project_name>
259         @param body: score to be added
260         @type body: L{ScenarioScore}
261         @in body: body
262         @param installer: installer type
263         @type installer: L{string}
264         @in installer: query
265         @required installer: True
266         @param version: version
267         @type version: L{string}
268         @in version: query
269         @required version: True
270         @param project: project name
271         @type project: L{string}
272         @in project: query
273         @required project: True
274         @return 200: score is created.
275         @raise 404:  scenario/installer/version/project not existed
276         """
277         self.do_update('scores',
278                        'post',
279                        locators={'scenario': scenario,
280                                  'installer': None,
281                                  'version': None,
282                                  'project': None})
283
284
285 class ScenarioTIsHandler(GenericScenarioUpdateHandler):
286     @swagger.operation(nickname="addTrustIndicatorRecord")
287     def post(self, scenario):
288         """
289         @description: add a new trust indicator record
290         @notes: add a new trust indicator record to a project
291             POST /api/v1/scenarios/<scenario_name>/trust_indicators? \
292                 installer=<installer_name>& \
293                 version=<version_name>& \
294                 project=<project_name>
295         @param body: trust indicator to be added
296         @type body: L{ScenarioTI}
297         @in body: body
298         @param installer: installer type
299         @type installer: L{string}
300         @in installer: query
301         @required installer: True
302         @param version: version
303         @type version: L{string}
304         @in version: query
305         @required version: True
306         @param project: project name
307         @type project: L{string}
308         @in project: query
309         @required project: True
310         @return 200: trust indicator is added.
311         @raise 404:  scenario/installer/version/project not existed
312         """
313         self.do_update('trust_indicators',
314                        'post',
315                        locators={'scenario': scenario,
316                                  'installer': None,
317                                  'version': None,
318                                  'project': None})
319
320
321 class ScenarioCustomsHandler(GenericScenarioUpdateHandler):
322     @swagger.operation(nickname="addCustomizedTestCases")
323     def post(self, scenario):
324         """
325         @description: add customized test cases
326         @notes: add several test cases to a project
327             POST /api/v1/scenarios/<scenario_name>/customs? \
328                 installer=<installer_name>& \
329                 version=<version_name>& \
330                 project=<project_name>
331         @param body: test cases to be added
332         @type body: C{list} of L{string}
333         @in body: body
334         @param installer: installer type
335         @type installer: L{string}
336         @in installer: query
337         @required installer: True
338         @param version: version
339         @type version: L{string}
340         @in version: query
341         @required version: True
342         @param project: project name
343         @type project: L{string}
344         @in project: query
345         @required project: True
346         @return 200: test cases are added.
347         @raise 404:  scenario/installer/version/project not existed
348         """
349         self.do_update('customs',
350                        'post',
351                        locators={'scenario': scenario,
352                                  'installer': None,
353                                  'version': None,
354                                  'project': None})
355
356     @swagger.operation(nickname="updateCustomizedTestCases")
357     def put(self, scenario):
358         """
359         @description: update customized test cases
360         @notes: substitute all the customized test cases
361             PUT /api/v1/scenarios/<scenario_name>/customs? \
362                 installer=<installer_name>& \
363                 version=<version_name>& \
364                 project=<project_name>
365         @param body: new supported test cases
366         @type body: C{list} of L{string}
367         @in body: body
368         @param installer: installer type
369         @type installer: L{string}
370         @in installer: query
371         @required installer: True
372         @param version: version
373         @type version: L{string}
374         @in version: query
375         @required version: True
376         @param project: project name
377         @type project: L{string}
378         @in project: query
379         @required project: True
380         @return 200: substitute test cases success.
381         @raise 404:  scenario/installer/version/project not existed
382         """
383         self.do_update('customs',
384                        'put',
385                        locators={'scenario': scenario,
386                                  'installer': None,
387                                  'version': None,
388                                  'project': None})
389
390     @swagger.operation(nickname="deleteCustomizedTestCases")
391     def delete(self, scenario):
392         """
393         @description: delete one or several customized test cases
394         @notes: delete one or some customized test cases
395             DELETE /api/v1/scenarios/<scenario_name>/customs? \
396                 installer=<installer_name>& \
397                 version=<version_name>& \
398                 project=<project_name>
399         @param body: test case(s) to be deleted
400         @type body: C{list} of L{string}
401         @in body: body
402         @param installer: installer type
403         @type installer: L{string}
404         @in installer: query
405         @required installer: True
406         @param version: version
407         @type version: L{string}
408         @in version: query
409         @required version: True
410         @param project: project name
411         @type project: L{string}
412         @in project: query
413         @required project: True
414         @return 200: delete test case(s) success.
415         @raise 404:  scenario/installer/version/project not existed
416         """
417         self.do_update('customs',
418                        'delete',
419                        locators={'scenario': scenario,
420                                  'installer': None,
421                                  'version': None,
422                                  'project': None})