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