tuning-box/tuning_box/library/resource_values.py

144 lines
5.9 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
from flask import current_app as app
import flask_restful
import six
from sqlalchemy import or_
from tuning_box import db
from tuning_box import library
from tuning_box.library import hierarchy_levels
from tuning_box.library import resource_keys_operation
class ResourceValues(flask_restful.Resource):
@db.with_transaction
def put(self, environment_id, levels, resource_id_or_name):
environment = db.Environment.query.get_or_404(environment_id)
res_def = library.get_resource_definition(
resource_id_or_name, environment_id)
level_value = hierarchy_levels.get_environment_level_value(
environment, levels)
esv = db.get_or_create(
db.ResourceValues,
environment=environment,
resource_definition=res_def,
level_value=level_value,
)
esv.values = flask.request.json
return None, 204
def _calculate_effective_values(self, result, level_value,
resource_values_idx, show_lookup,
lookup_path):
level_value_id = getattr(level_value, 'id', None)
if level_value_id in resource_values_idx:
resource_value = resource_values_idx[level_value_id]
if show_lookup:
values = ((k, (v, lookup_path)) for k, v in
six.iteritems(resource_value.values))
overrides = ((k, (v, lookup_path)) for k, v in
six.iteritems(resource_value.overrides))
else:
values = resource_value.values
overrides = resource_value.overrides
result.update(values)
result.update(overrides)
@db.with_transaction
def get(self, environment_id, resource_id_or_name, levels):
app.logger.debug("Getting resource value. Env: %s, "
"resource: %s, levels: %s", environment_id,
resource_id_or_name, levels)
environment = db.Environment.query.get_or_404(environment_id)
res_def = library.get_resource_definition(
resource_id_or_name, environment_id)
level_values = list(hierarchy_levels.iter_environment_level_values(
environment, levels))
level_values_ids = [l.id for l in level_values]
app.logger.debug("Got level values ids: %s", level_values_ids)
if 'effective' in flask.request.args:
app.logger.debug("Getting effective resource value. Env: %s, "
"resource: %s, levels: %s", environment_id,
resource_id_or_name, levels)
show_lookup = 'show_lookup' in flask.request.args
resource_values = db.ResourceValues.query.filter(
or_(
db.ResourceValues.level_value_id.in_(level_values_ids),
db.ResourceValues.level_value_id.is_(None)
),
db.ResourceValues.resource_definition == res_def,
db.ResourceValues.environment == environment
).all()
app.logger.debug("Processing values for resource: %s, env: %s. "
"Loaded resource values: %s",
res_def.id, environment.id, len(resource_values))
# Creating index of resource_values by level_value_id
resource_values_idx = {r.level_value_id: r
for r in resource_values}
app.logger.debug("Resource values index size: %s",
len(resource_values_idx))
result = {}
lookup_path = '/'
self._calculate_effective_values(
result, None, resource_values_idx, show_lookup,
lookup_path)
for level_value in level_values:
name = level_value.level.name
value = level_value.value
lookup_path += name + '/' + value + '/'
self._calculate_effective_values(
result, level_value, resource_values_idx, show_lookup,
lookup_path)
app.logger.debug("Effective values got for resource: "
"%s, env: %s", res_def.id, environment.id)
return result
else:
if not level_values:
level_value = None
else:
level_value = level_values[-1]
resource_values = db.ResourceValues.query.filter_by(
resource_definition=res_def,
environment=environment,
level_value=level_value,
).one_or_none()
app.logger.debug("Values got for resource: "
"%s, env: %s", res_def.id, environment.id)
if not resource_values:
return {}
return resource_values.values
class ResourceValuesKeys(flask_restful.Resource,
resource_keys_operation.ResourceKeysMixin):
def put(self, environment_id, levels, resource_id_or_name, operation):
return self.patch(environment_id, levels,
resource_id_or_name, operation)
def patch(self, environment_id, levels, resource_id_or_name, operation):
self._do_update(environment_id, levels, resource_id_or_name,
operation, 'values')
return None, 204