Merge "bugfix: query doesn't work well with period=1"
[releng.git] / utils / test / testapi / opnfv_testapi / resources / scenario_handlers.py
1 import functools
2
3 from opnfv_testapi.common import message
4 from opnfv_testapi.common import raises
5 from opnfv_testapi.resources import handlers
6 import opnfv_testapi.resources.scenario_models as models
7 from opnfv_testapi.tornado_swagger import swagger
8
9
10 class GenericScenarioHandler(handlers.GenericApiHandler):
11     def __init__(self, application, request, **kwargs):
12         super(GenericScenarioHandler, self).__init__(application,
13                                                      request,
14                                                      **kwargs)
15         self.table = self.db_scenarios
16         self.table_cls = models.Scenario
17
18
19 class ScenariosCLHandler(GenericScenarioHandler):
20     @swagger.operation(nickname="queryScenarios")
21     def get(self):
22         """
23             @description: Retrieve scenario(s).
24             @notes: Retrieve scenario(s)
25                 Available filters for this request are :
26                  - name : scenario name
27
28                 GET /scenarios?name=scenario_1
29             @param name: scenario name
30             @type name: L{string}
31             @in name: query
32             @required name: False
33             @param installer: installer type
34             @type installer: L{string}
35             @in installer: query
36             @required installer: False
37             @param version: version
38             @type version: L{string}
39             @in version: query
40             @required version: False
41             @param project: project name
42             @type project: L{string}
43             @in project: query
44             @required project: False
45             @return 200: all scenarios satisfy queries,
46                          empty list if no scenario is found
47             @rtype: L{Scenarios}
48         """
49
50         def _set_query():
51             query = dict()
52             elem_query = dict()
53             for k in self.request.query_arguments.keys():
54                 v = self.get_query_argument(k)
55                 if k == 'installer':
56                     elem_query["installer"] = v
57                 elif k == 'version':
58                     elem_query["versions.version"] = v
59                 elif k == 'project':
60                     elem_query["versions.projects.project"] = v
61                 else:
62                     query[k] = v
63             if elem_query:
64                 query['installers'] = {'$elemMatch': elem_query}
65             return query
66
67         self._list(query=_set_query())
68
69     @swagger.operation(nickname="createScenario")
70     def post(self):
71         """
72             @description: create a new scenario by name
73             @param body: scenario to be created
74             @type body: L{ScenarioCreateRequest}
75             @in body: body
76             @rtype: L{CreateResponse}
77             @return 200: scenario is created.
78             @raise 403: scenario already exists
79             @raise 400:  body or name not provided
80         """
81         def query():
82             return {'name': self.json_args.get('name')}
83         miss_fields = ['name']
84         self._create(miss_fields=miss_fields, query=query)
85
86
87 class ScenarioGURHandler(GenericScenarioHandler):
88     @swagger.operation(nickname='getScenarioByName')
89     def get(self, name):
90         """
91             @description: get a single scenario by name
92             @rtype: L{Scenario}
93             @return 200: scenario exist
94             @raise 404: scenario not exist
95         """
96         self._get_one(query={'name': name})
97         pass
98
99     @swagger.operation(nickname="updateScenarioByName")
100     def put(self, name):
101         """
102             @description: update a single scenario by name
103             @param body: fields to be updated
104             @type body: L{ScenarioUpdateRequest}
105             @in body: body
106             @rtype: L{Scenario}
107             @return 200: update success
108             @raise 404: scenario not exist
109             @raise 403: nothing to update
110         """
111         query = {'name': name}
112         db_keys = ['name']
113         self._update(query=query, db_keys=db_keys)
114
115     @swagger.operation(nickname="deleteScenarioByName")
116     def delete(self, name):
117         """
118         @description: delete a scenario by name
119         @return 200: delete success
120         @raise 404: scenario not exist:
121         """
122
123         self._delete(query={'name': name})
124
125     def _update_query(self, keys, data):
126         query = dict()
127         if self._is_rename():
128             new = self._term.get('name')
129             if data.get('name') != new:
130                 query['name'] = new
131
132         return query
133
134     def _update_requests(self, data):
135         updates = {
136             ('name', 'update'): self._update_requests_rename,
137             ('installer', 'add'): self._update_requests_add_installer,
138             ('installer', 'delete'): self._update_requests_delete_installer,
139             ('version', 'add'): self._update_requests_add_version,
140             ('version', 'delete'): self._update_requests_delete_version,
141             ('owner', 'update'): self._update_requests_change_owner,
142             ('project', 'add'): self._update_requests_add_project,
143             ('project', 'delete'): self._update_requests_delete_project,
144             ('customs', 'add'): self._update_requests_add_customs,
145             ('customs', 'delete'): self._update_requests_delete_customs,
146             ('score', 'add'): self._update_requests_add_score,
147             ('trust_indicator', 'add'): self._update_requests_add_ti,
148         }
149
150         updates[(self._field, self._op)](data)
151
152         return data.format()
153
154     def _iter_installers(xstep):
155         @functools.wraps(xstep)
156         def magic(self, data):
157             [xstep(self, installer)
158              for installer in self._filter_installers(data.installers)]
159         return magic
160
161     def _iter_versions(xstep):
162         @functools.wraps(xstep)
163         def magic(self, installer):
164             [xstep(self, version)
165              for version in (self._filter_versions(installer.versions))]
166         return magic
167
168     def _iter_projects(xstep):
169         @functools.wraps(xstep)
170         def magic(self, version):
171             [xstep(self, project)
172              for project in (self._filter_projects(version.projects))]
173         return magic
174
175     def _update_requests_rename(self, data):
176         data.name = self._term.get('name')
177         if not data.name:
178             raises.BadRequest(message.missing('name'))
179
180     def _update_requests_add_installer(self, data):
181         data.installers.append(models.ScenarioInstaller.from_dict(self._term))
182
183     def _update_requests_delete_installer(self, data):
184         data.installers = self._remove_installers(data.installers)
185
186     @_iter_installers
187     def _update_requests_add_version(self, installer):
188         installer.versions.append(models.ScenarioVersion.from_dict(self._term))
189
190     @_iter_installers
191     def _update_requests_delete_version(self, installer):
192         installer.versions = self._remove_versions(installer.versions)
193
194     @_iter_installers
195     @_iter_versions
196     def _update_requests_change_owner(self, version):
197         version.owner = self._term.get('owner')
198
199     @_iter_installers
200     @_iter_versions
201     def _update_requests_add_project(self, version):
202         version.projects.append(models.ScenarioProject.from_dict(self._term))
203
204     @_iter_installers
205     @_iter_versions
206     def _update_requests_delete_project(self, version):
207         version.projects = self._remove_projects(version.projects)
208
209     @_iter_installers
210     @_iter_versions
211     @_iter_projects
212     def _update_requests_add_customs(self, project):
213         project.customs = list(set(project.customs + self._term))
214
215     @_iter_installers
216     @_iter_versions
217     @_iter_projects
218     def _update_requests_delete_customs(self, project):
219         project.customs = filter(
220             lambda f: f not in self._term,
221             project.customs)
222
223     @_iter_installers
224     @_iter_versions
225     @_iter_projects
226     def _update_requests_add_score(self, project):
227         project.scores.append(
228             models.ScenarioScore.from_dict(self._term))
229
230     @_iter_installers
231     @_iter_versions
232     @_iter_projects
233     def _update_requests_add_ti(self, project):
234         project.trust_indicators.append(
235             models.ScenarioTI.from_dict(self._term))
236
237     def _is_rename(self):
238         return self._field == 'name' and self._op == 'update'
239
240     def _remove_installers(self, installers):
241         return self._remove('installer', installers)
242
243     def _filter_installers(self, installers):
244         return self._filter('installer', installers)
245
246     def _remove_versions(self, versions):
247         return self._remove('version', versions)
248
249     def _filter_versions(self, versions):
250         return self._filter('version', versions)
251
252     def _remove_projects(self, projects):
253         return self._remove('project', projects)
254
255     def _filter_projects(self, projects):
256         return self._filter('project', projects)
257
258     def _remove(self, field, fields):
259         return filter(
260             lambda f: getattr(f, field) != self._locate.get(field),
261             fields)
262
263     def _filter(self, field, fields):
264         return filter(
265             lambda f: getattr(f, field) == self._locate.get(field),
266             fields)
267
268     @property
269     def _field(self):
270         return self.json_args.get('field')
271
272     @property
273     def _op(self):
274         return self.json_args.get('op')
275
276     @property
277     def _locate(self):
278         return self.json_args.get('locate')
279
280     @property
281     def _term(self):
282         return self.json_args.get('term')