Merge "Implement watcher datamodel list in watcher-api"

This commit is contained in:
Zuul 2019-09-10 07:34:13 +00:00 committed by Gerrit Code Review
commit f274ef87ed
8 changed files with 201 additions and 2 deletions

View File

@ -35,6 +35,7 @@ from watcher.api.controllers.v1 import action
from watcher.api.controllers.v1 import action_plan
from watcher.api.controllers.v1 import audit
from watcher.api.controllers.v1 import audit_template
from watcher.api.controllers.v1 import data_model
from watcher.api.controllers.v1 import goal
from watcher.api.controllers.v1 import scoring_engine
from watcher.api.controllers.v1 import service
@ -114,6 +115,9 @@ class V1(APIBase):
audits = [link.Link]
"""Links to the audits resource"""
data_model = [link.Link]
"""Links to the data model resource"""
actions = [link.Link]
"""Links to the actions resource"""
@ -158,6 +162,13 @@ class V1(APIBase):
'audits', '',
bookmark=True)
]
v1.data_model = [link.Link.make_link('self', pecan.request.host_url,
'data_model', ''),
link.Link.make_link('bookmark',
pecan.request.host_url,
'data_model', '',
bookmark=True)
]
v1.actions = [link.Link.make_link('self', pecan.request.host_url,
'actions', ''),
link.Link.make_link('bookmark',
@ -202,6 +213,7 @@ class Controller(rest.RestController):
scoring_engines = scoring_engine.ScoringEngineController()
services = service.ServicesController()
strategies = strategy.StrategiesController()
data_model = data_model.DataModelController()
@wsme_pecan.wsexpose(V1)
def get(self):

View File

@ -0,0 +1,68 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2019 ZTE Corporation
#
# 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.
"""
An Interface for users and admin to List Data Model.
"""
import pecan
from pecan import rest
from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan
from watcher.api.controllers.v1 import types
from watcher.common import exception
from watcher.common import policy
from watcher.decision_engine import rpcapi
class DataModelController(rest.RestController):
"""REST controller for data model"""
def __init__(self):
super(DataModelController, self).__init__()
from_data_model = False
"""A flag to indicate if the requests to this controller are coming
from the top-level resource DataModel."""
@wsme_pecan.wsexpose(wtypes.text, wtypes.text, types.uuid)
def get_all(self, data_model_type='compute', audit_uuid=None):
"""Retrieve information about the given data model.
:param data_model_type: The type of data model user wants to list.
Supported values: compute.
Future support values: storage, baremetal.
The default value is compute.
:param audit_uuid: The UUID of the audit, used to filter data model
by the scope in audit.
"""
if self.from_data_model:
raise exception.OperationNotPermitted
allowed_data_model_type = [
'compute',
]
if data_model_type not in allowed_data_model_type:
raise exception.DataModelTypeNotFound(
data_model_type=data_model_type)
context = pecan.request.context
de_client = rpcapi.DecisionEngineAPI()
policy.enforce(context, 'data_model:get_all',
action='data_model:get_all')
rpc_all_data_model = de_client.get_data_model_info(
context,
data_model_type,
audit_uuid)
return rpc_all_data_model

View File

@ -210,6 +210,10 @@ class InvalidIntervalOrCron(Invalid):
msg_fmt = _("Expected an interval or cron syntax but received %(name)s")
class DataModelTypeNotFound(ResourceNotFound):
msg_fmt = _("The %(data_model_type)s data model could not be found")
class GoalNotFound(ResourceNotFound):
msg_fmt = _("Goal %(goal)s could not be found")

View File

@ -17,6 +17,7 @@ from watcher.common.policies import action_plan
from watcher.common.policies import audit
from watcher.common.policies import audit_template
from watcher.common.policies import base
from watcher.common.policies import data_model
from watcher.common.policies import goal
from watcher.common.policies import scoring_engine
from watcher.common.policies import service
@ -30,6 +31,7 @@ def list_rules():
action_plan.list_rules(),
audit.list_rules(),
audit_template.list_rules(),
data_model.list_rules(),
goal.list_rules(),
scoring_engine.list_rules(),
service.list_rules(),

View File

@ -0,0 +1,37 @@
# Copyright 2019 ZTE Corporation.
#
# 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.
from oslo_policy import policy
from watcher.common.policies import base
DATA_MODEL = 'data_model:%s'
rules = [
policy.DocumentedRuleDefault(
name=DATA_MODEL % 'get_all',
check_str=base.RULE_ADMIN_API,
description='List data model.',
operations=[
{
'path': '/v1/data_model',
'method': 'GET'
}
]
),
]
def list_rules():
return rules

View File

@ -37,7 +37,7 @@ class TestV1Root(base.FunctionalTest):
not_resources = ('id', 'links', 'media_types')
actual_resources = tuple(set(data.keys()) - set(not_resources))
expected_resources = ('audit_templates', 'audits', 'actions',
'action_plans', 'scoring_engines',
'action_plans', 'data_model', 'scoring_engines',
'services')
self.assertEqual(sorted(expected_resources), sorted(actual_resources))

View File

@ -0,0 +1,74 @@
# Copyright 2019 ZTE corporation.
# All Rights Reserved.
#
# 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 mock
from oslo_serialization import jsonutils
from watcher.decision_engine import rpcapi as deapi
from watcher.tests.api import base as api_base
class TestListDataModel(api_base.FunctionalTest):
def setUp(self):
super(TestListDataModel, self).setUp()
p_dcapi = mock.patch.object(deapi, 'DecisionEngineAPI')
self.mock_dcapi = p_dcapi.start()
self.mock_dcapi().get_data_model_info.return_value = \
'fake_response_value'
self.addCleanup(p_dcapi.stop)
def test_get_all(self):
response = self.get_json('/data_model/?data_model_type=compute')
self.assertEqual('fake_response_value', response)
class TestDataModelPolicyEnforcement(api_base.FunctionalTest):
def setUp(self):
super(TestDataModelPolicyEnforcement, self).setUp()
p_dcapi = mock.patch.object(deapi, 'DecisionEngineAPI')
self.mock_dcapi = p_dcapi.start()
self.addCleanup(p_dcapi.stop)
def _common_policy_check(self, rule, func, *arg, **kwarg):
self.policy.set_rules({
"admin_api": "(role:admin or role:administrator)",
"default": "rule:admin_api",
rule: "rule:defaut"})
response = func(*arg, **kwarg)
self.assertEqual(403, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(
"Policy doesn't allow %s to be performed." % rule,
jsonutils.loads(response.json['error_message'])['faultstring'])
def test_policy_disallow_get_all(self):
self._common_policy_check(
"data_model:get_all", self.get_json,
"/data_model/?data_model_type=compute",
expect_errors=True)
class TestDataModelEnforcementWithAdminContext(
TestListDataModel, api_base.AdminRoleTest):
def setUp(self):
super(TestDataModelEnforcementWithAdminContext, self).setUp()
self.policy.set_rules({
"admin_api": "(role:admin or role:administrator)",
"default": "rule:admin_api",
"data_model:get_all": "rule:default"})

View File

@ -58,7 +58,9 @@ policy_data = """
"service:detail": "",
"service:get": "",
"service:get_all": ""
"service:get_all": "",
"data_model:get_all": ""
}
"""