Add a new microversion for data model API

microversion 1.3 for list data model API

Change-Id: Ibf8774a48c3d13ca9762bd5319f5e1ce2ed82b2f
Closes-Bug: #1854121
This commit is contained in:
licanwei 2019-11-29 11:52:42 +08:00
parent 42fea1c568
commit 6f43f2b003
7 changed files with 59 additions and 11 deletions

View File

@ -30,3 +30,7 @@ audits.
--- ---
Added ``force`` into create audit request. If ``force`` is true, Added ``force`` into create audit request. If ``force`` is true,
audit will be executed despite of ongoing actionplan. audit will be executed despite of ongoing actionplan.
1.3
---
Added list data model API.

View File

@ -40,6 +40,7 @@ from watcher.api.controllers.v1 import goal
from watcher.api.controllers.v1 import scoring_engine from watcher.api.controllers.v1 import scoring_engine
from watcher.api.controllers.v1 import service from watcher.api.controllers.v1 import service
from watcher.api.controllers.v1 import strategy from watcher.api.controllers.v1 import strategy
from watcher.api.controllers.v1 import utils
from watcher.api.controllers.v1 import versions from watcher.api.controllers.v1 import versions
@ -163,6 +164,7 @@ class V1(APIBase):
'audits', '', 'audits', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_list_datamodel():
v1.data_model = [link.Link.make_link('self', base_url, v1.data_model = [link.Link.make_link('self', base_url,
'data_model', ''), 'data_model', ''),
link.Link.make_link('bookmark', link.Link.make_link('bookmark',

View File

@ -24,6 +24,7 @@ from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan import wsmeext.pecan as wsme_pecan
from watcher.api.controllers.v1 import types from watcher.api.controllers.v1 import types
from watcher.api.controllers.v1 import utils
from watcher.common import exception from watcher.common import exception
from watcher.common import policy from watcher.common import policy
from watcher.decision_engine import rpcapi from watcher.decision_engine import rpcapi
@ -49,6 +50,8 @@ class DataModelController(rest.RestController):
:param audit_uuid: The UUID of the audit, used to filter data model :param audit_uuid: The UUID of the audit, used to filter data model
by the scope in audit. by the scope in audit.
""" """
if not utils.allow_list_datamodel():
raise exception.NotAcceptable
if self.from_data_model: if self.from_data_model:
raise exception.OperationNotPermitted raise exception.OperationNotPermitted
allowed_data_model_type = [ allowed_data_model_type = [

View File

@ -176,3 +176,12 @@ def allow_force():
""" """
return pecan.request.version.minor >= ( return pecan.request.version.minor >= (
versions.VERSIONS.MINOR_2_FORCE.value) versions.VERSIONS.MINOR_2_FORCE.value)
def allow_list_datamodel():
"""Check if we should support list data model API.
Version 1.3 of the API added support to list data model.
"""
return pecan.request.version.minor >= (
versions.VERSIONS.MINOR_3_DATAMODEL.value)

View File

@ -21,7 +21,8 @@ class VERSIONS(enum.Enum):
MINOR_0_ROCKY = 0 # v1.0: corresponds to Rocky API MINOR_0_ROCKY = 0 # v1.0: corresponds to Rocky API
MINOR_1_START_END_TIMING = 1 # v1.1: Add start/end timei for audit MINOR_1_START_END_TIMING = 1 # v1.1: Add start/end timei for audit
MINOR_2_FORCE = 2 # v1.2: Add force field to audit MINOR_2_FORCE = 2 # v1.2: Add force field to audit
MINOR_MAX_VERSION = 2 MINOR_3_DATAMODEL = 3 # v1.3: Add list datamodel API
MINOR_MAX_VERSION = 3
# This is the version 1 API # This is the version 1 API
BASE_VERSION = 1 BASE_VERSION = 1

View File

@ -27,8 +27,9 @@ class TestRoot(base.FunctionalTest):
class TestV1Root(base.FunctionalTest): class TestV1Root(base.FunctionalTest):
def test_get_v1_root(self): def test_get_v1_root_all(self):
data = self.get_json('/') data = self.get_json(
'/', headers={'OpenStack-API-Version': 'infra-optim 1.3'})
self.assertEqual('v1', data['id']) self.assertEqual('v1', data['id'])
# Check fields are not empty # Check fields are not empty
for f in data.keys(): for f in data.keys():
@ -43,3 +44,21 @@ class TestV1Root(base.FunctionalTest):
self.assertIn({'type': 'application/vnd.openstack.watcher.v1+json', self.assertIn({'type': 'application/vnd.openstack.watcher.v1+json',
'base': 'application/json'}, data['media_types']) 'base': 'application/json'}, data['media_types'])
def test_get_v1_root_without_datamodel(self):
data = self.get_json(
'/', headers={'OpenStack-API-Version': 'infra-optim 1.2'})
self.assertEqual('v1', data['id'])
# Check fields are not empty
for f in data.keys():
self.assertNotIn(f, ['', []])
# Check if all known resources are present and there are no extra ones.
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',
'services')
self.assertEqual(sorted(expected_resources), sorted(actual_resources))
self.assertIn({'type': 'application/vnd.openstack.watcher.v1+json',
'base': 'application/json'}, data['media_types'])

View File

@ -32,9 +32,18 @@ class TestListDataModel(api_base.FunctionalTest):
self.addCleanup(p_dcapi.stop) self.addCleanup(p_dcapi.stop)
def test_get_all(self): def test_get_all(self):
response = self.get_json('/data_model/?data_model_type=compute') response = self.get_json(
'/data_model/?data_model_type=compute',
headers={'OpenStack-API-Version': 'infra-optim 1.3'})
self.assertEqual('fake_response_value', response) self.assertEqual('fake_response_value', response)
def test_get_all_not_acceptable(self):
response = self.get_json(
'/data_model/?data_model_type=compute',
headers={'OpenStack-API-Version': 'infra-optim 1.2'},
expect_errors=True)
self.assertEqual(406, response.status_int)
class TestDataModelPolicyEnforcement(api_base.FunctionalTest): class TestDataModelPolicyEnforcement(api_base.FunctionalTest):
@ -60,6 +69,7 @@ class TestDataModelPolicyEnforcement(api_base.FunctionalTest):
self._common_policy_check( self._common_policy_check(
"data_model:get_all", self.get_json, "data_model:get_all", self.get_json,
"/data_model/?data_model_type=compute", "/data_model/?data_model_type=compute",
headers={'OpenStack-API-Version': 'infra-optim 1.3'},
expect_errors=True) expect_errors=True)