tuning-box/tuning_box/library/environments.py

143 lines
5.1 KiB
Python

# 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.
import flask
import flask_restful
from flask_restful import fields
from tuning_box import db
from tuning_box import errors
from tuning_box import library
environment_fields = {
'id': fields.Integer,
'components': fields.List(fields.Integer(attribute='id')),
'hierarchy_levels': fields.List(fields.String(attribute='name')),
}
def prepare_env_for_output(env):
# Proper order of levels can't be provided by ORM backref
hierarchy_levels = db.EnvironmentHierarchyLevel.get_for_environment(env)
return {'id': env.id, 'components': env.components,
'hierarchy_levels': hierarchy_levels}
class EnvironmentsCollection(flask_restful.Resource):
method_decorators = [flask_restful.marshal_with(environment_fields)]
def get(self):
envs = db.Environment.query.order_by(db.Environment.id).all()
result = []
for env in envs:
result.append(prepare_env_for_output(env))
return result, 200
def _check_components(self, components):
identities = set()
duplicates = set()
id_names = ('id', 'name')
for component in components:
for id_name in id_names:
value = getattr(component, id_name)
if value not in identities:
identities.add(value)
else:
duplicates.add(value)
if duplicates:
raise errors.TuningboxIntegrityError(
"Components duplicates: {0}".format(duplicates))
@db.with_transaction
def post(self):
component_ids = flask.request.json['components']
components = [db.Component.query.get_by_id_or_name(i)
for i in component_ids]
self._check_components(components)
hierarchy_levels = []
level = None
for name in flask.request.json['hierarchy_levels']:
level = db.EnvironmentHierarchyLevel(name=name, parent=level)
hierarchy_levels.append(level)
environment = db.Environment(components=components,
hierarchy_levels=hierarchy_levels)
if 'id' in flask.request.json:
environment.id = flask.request.json['id']
db.db.session.add(environment)
return prepare_env_for_output(environment), 201
class Environment(flask_restful.Resource):
method_decorators = [flask_restful.marshal_with(environment_fields)]
def get(self, environment_id):
env = db.get_or_404(db.Environment, environment_id)
return prepare_env_for_output(env), 200
def _update_components(self, environment, components):
if components is not None:
new_components = library.load_objects_by_id_or_name(
db.Component, components)
environment.components = new_components
def _update_hierarchy_levels(self, environment, hierarchy_levels_names):
if hierarchy_levels_names is not None:
old_hierarchy_levels = db.EnvironmentHierarchyLevel.query.filter(
db.EnvironmentHierarchyLevel.environment_id == environment.id
).all()
new_hierarchy_levels = []
for level_name in hierarchy_levels_names:
level = db.get_or_create(
db.EnvironmentHierarchyLevel,
name=level_name,
environment=environment
)
new_hierarchy_levels.append(level)
parent_id = None
for level in new_hierarchy_levels:
level.parent_id = parent_id
parent_id = level.id
for old_level in old_hierarchy_levels:
if old_level not in new_hierarchy_levels:
db.db.session.delete(old_level)
environment.hierarchy_levels = new_hierarchy_levels
@db.with_transaction
def _perform_update(self, environment_id):
environment = db.get_or_404(db.Environment, environment_id)
update_by = flask.request.json
components = update_by.get('components')
self._update_components(environment, components)
hierarchy_levels = update_by.get('hierarchy_levels')
self._update_hierarchy_levels(environment, hierarchy_levels)
def put(self, environment_id):
return self.patch(environment_id)
def patch(self, environment_id):
self._perform_update(environment_id)
return None, 204
@db.with_transaction
def delete(self, environment_id):
environment = db.get_or_404(db.Environment, environment_id)
db.db.session.delete(environment)
return None, 204