Support to list software configs
APIImpact List software configs GET /v1/{tenant_id}/software_configs Request params(optional) limit,marker Json response example {'software_configs':[ {'creation_time': '2015-06-25T07:15:56', 'group': 'Heat::Ungrouped', 'id': 'de879d1c-c9a5-4635-ba29-08a5690fec27', 'name': 'foo'}] } Change-Id: Iad691672874b64b393b85d2eb9a55b22facbd263 Closes-Bug: #1464248
This commit is contained in:
parent
3fd6b53079
commit
7975d8b46a
@ -59,6 +59,8 @@
|
|||||||
"stacks:list_snapshots": "rule:deny_stack_user",
|
"stacks:list_snapshots": "rule:deny_stack_user",
|
||||||
"stacks:restore_snapshot": "rule:deny_stack_user",
|
"stacks:restore_snapshot": "rule:deny_stack_user",
|
||||||
|
|
||||||
|
"software_configs:global_index": "rule:deny_everybody",
|
||||||
|
"software_configs:index": "rule:deny_stack_user",
|
||||||
"software_configs:create": "rule:deny_stack_user",
|
"software_configs:create": "rule:deny_stack_user",
|
||||||
"software_configs:show": "rule:deny_stack_user",
|
"software_configs:show": "rule:deny_stack_user",
|
||||||
"software_configs:delete": "rule:deny_stack_user",
|
"software_configs:delete": "rule:deny_stack_user",
|
||||||
|
@ -334,6 +334,12 @@ class API(wsgi.Router):
|
|||||||
connect(controller=software_config_resource,
|
connect(controller=software_config_resource,
|
||||||
path_prefix='/{tenant_id}/software_configs',
|
path_prefix='/{tenant_id}/software_configs',
|
||||||
routes=[
|
routes=[
|
||||||
|
{
|
||||||
|
'name': 'software_config_index',
|
||||||
|
'url': '',
|
||||||
|
'action': 'index',
|
||||||
|
'method': 'GET'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'name': 'software_config_create',
|
'name': 'software_config_create',
|
||||||
'url': '',
|
'url': '',
|
||||||
|
@ -11,11 +11,14 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import six
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
from heat.api.openstack.v1 import util
|
from heat.api.openstack.v1 import util
|
||||||
|
from heat.common import param_utils
|
||||||
from heat.common import serializers
|
from heat.common import serializers
|
||||||
from heat.common import wsgi
|
from heat.common import wsgi
|
||||||
|
from heat.rpc import api as rpc_api
|
||||||
from heat.rpc import client as rpc_client
|
from heat.rpc import client as rpc_client
|
||||||
|
|
||||||
|
|
||||||
@ -34,6 +37,44 @@ class SoftwareConfigController(object):
|
|||||||
def default(self, req, **args):
|
def default(self, req, **args):
|
||||||
raise exc.HTTPNotFound()
|
raise exc.HTTPNotFound()
|
||||||
|
|
||||||
|
def _extract_bool_param(self, name, value):
|
||||||
|
try:
|
||||||
|
return param_utils.extract_bool(name, value)
|
||||||
|
except ValueError as e:
|
||||||
|
raise exc.HTTPBadRequest(six.text_type(e))
|
||||||
|
|
||||||
|
def _index(self, req, tenant_safe=True):
|
||||||
|
whitelist = {
|
||||||
|
'limit': 'single',
|
||||||
|
'marker': 'single'
|
||||||
|
}
|
||||||
|
params = util.get_allowed_params(req.params, whitelist)
|
||||||
|
scs = self.rpc_client.list_software_configs(req.context,
|
||||||
|
tenant_safe=tenant_safe,
|
||||||
|
**params)
|
||||||
|
return {'software_configs': scs}
|
||||||
|
|
||||||
|
@util.policy_enforce
|
||||||
|
def global_index(self, req):
|
||||||
|
return self._index(req, tenant_safe=False)
|
||||||
|
|
||||||
|
@util.policy_enforce
|
||||||
|
def index(self, req):
|
||||||
|
"""
|
||||||
|
Lists summary information for all software configs
|
||||||
|
"""
|
||||||
|
global_tenant = False
|
||||||
|
name = rpc_api.PARAM_GLOBAL_TENANT
|
||||||
|
if name in req.params:
|
||||||
|
global_tenant = self._extract_bool_param(
|
||||||
|
name,
|
||||||
|
req.params.get(name))
|
||||||
|
|
||||||
|
if global_tenant:
|
||||||
|
return self.global_index(req, req.context.tenant_id)
|
||||||
|
|
||||||
|
return self._index(req)
|
||||||
|
|
||||||
@util.policy_enforce
|
@util.policy_enforce
|
||||||
def show(self, req, config_id):
|
def show(self, req, config_id):
|
||||||
"""
|
"""
|
||||||
|
@ -306,6 +306,14 @@ def software_config_get(context, config_id):
|
|||||||
return IMPL.software_config_get(context, config_id)
|
return IMPL.software_config_get(context, config_id)
|
||||||
|
|
||||||
|
|
||||||
|
def software_config_get_all(context, limit=None, marker=None,
|
||||||
|
tenant_safe=True):
|
||||||
|
return IMPL.software_config_get_all(context,
|
||||||
|
limit=limit,
|
||||||
|
marker=marker,
|
||||||
|
tenant_safe=tenant_safe)
|
||||||
|
|
||||||
|
|
||||||
def software_config_delete(context, config_id):
|
def software_config_delete(context, config_id):
|
||||||
return IMPL.software_config_delete(context, config_id)
|
return IMPL.software_config_delete(context, config_id)
|
||||||
|
|
||||||
|
@ -870,6 +870,15 @@ def software_config_get(context, config_id):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def software_config_get_all(context, limit=None, marker=None,
|
||||||
|
tenant_safe=True):
|
||||||
|
query = model_query(context, models.SoftwareConfig)
|
||||||
|
if tenant_safe:
|
||||||
|
query = query.filter_by(tenant=context.tenant_id)
|
||||||
|
return _paginate_query(context, query, models.SoftwareConfig,
|
||||||
|
limit=limit, marker=marker).all()
|
||||||
|
|
||||||
|
|
||||||
def software_config_delete(context, config_id):
|
def software_config_delete(context, config_id):
|
||||||
config = software_config_get(context, config_id)
|
config = software_config_get(context, config_id)
|
||||||
session = orm_session.Session.object_session(config)
|
session = orm_session.Session.object_session(config)
|
||||||
|
@ -403,19 +403,20 @@ def format_validate_parameter(param):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def format_software_config(sc):
|
def format_software_config(sc, detail=True):
|
||||||
if sc is None:
|
if sc is None:
|
||||||
return
|
return
|
||||||
result = {
|
result = {
|
||||||
rpc_api.SOFTWARE_CONFIG_ID: sc.id,
|
rpc_api.SOFTWARE_CONFIG_ID: sc.id,
|
||||||
rpc_api.SOFTWARE_CONFIG_NAME: sc.name,
|
rpc_api.SOFTWARE_CONFIG_NAME: sc.name,
|
||||||
rpc_api.SOFTWARE_CONFIG_GROUP: sc.group,
|
rpc_api.SOFTWARE_CONFIG_GROUP: sc.group,
|
||||||
rpc_api.SOFTWARE_CONFIG_CONFIG: sc.config['config'],
|
rpc_api.SOFTWARE_CONFIG_CREATION_TIME: sc.created_at.isoformat()
|
||||||
rpc_api.SOFTWARE_CONFIG_INPUTS: sc.config['inputs'],
|
|
||||||
rpc_api.SOFTWARE_CONFIG_OUTPUTS: sc.config['outputs'],
|
|
||||||
rpc_api.SOFTWARE_CONFIG_OPTIONS: sc.config['options'],
|
|
||||||
rpc_api.SOFTWARE_CONFIG_CREATION_TIME: sc.created_at.isoformat(),
|
|
||||||
}
|
}
|
||||||
|
if detail:
|
||||||
|
result[rpc_api.SOFTWARE_CONFIG_CONFIG] = sc.config['config']
|
||||||
|
result[rpc_api.SOFTWARE_CONFIG_INPUTS] = sc.config['inputs']
|
||||||
|
result[rpc_api.SOFTWARE_CONFIG_OUTPUTS] = sc.config['outputs']
|
||||||
|
result[rpc_api.SOFTWARE_CONFIG_OPTIONS] = sc.config['options']
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ class EngineService(service.Service):
|
|||||||
by the RPC caller.
|
by the RPC caller.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RPC_API_VERSION = '1.9'
|
RPC_API_VERSION = '1.10'
|
||||||
|
|
||||||
def __init__(self, host, topic, manager=None):
|
def __init__(self, host, topic, manager=None):
|
||||||
super(EngineService, self).__init__()
|
super(EngineService, self).__init__()
|
||||||
@ -1477,6 +1477,15 @@ class EngineService(service.Service):
|
|||||||
def show_software_config(self, cnxt, config_id):
|
def show_software_config(self, cnxt, config_id):
|
||||||
return self.software_config.show_software_config(cnxt, config_id)
|
return self.software_config.show_software_config(cnxt, config_id)
|
||||||
|
|
||||||
|
@context.request_context
|
||||||
|
def list_software_configs(self, cnxt, limit=None, marker=None,
|
||||||
|
tenant_safe=True):
|
||||||
|
return self.software_config.list_software_configs(
|
||||||
|
cnxt,
|
||||||
|
limit=limit,
|
||||||
|
marker=marker,
|
||||||
|
tenant_safe=tenant_safe)
|
||||||
|
|
||||||
@context.request_context
|
@context.request_context
|
||||||
def create_software_config(self, cnxt, group, name, config,
|
def create_software_config(self, cnxt, group, name, config,
|
||||||
inputs, outputs, options):
|
inputs, outputs, options):
|
||||||
|
@ -36,6 +36,16 @@ class SoftwareConfigService(service.Service):
|
|||||||
sc = software_config_object.SoftwareConfig.get_by_id(cnxt, config_id)
|
sc = software_config_object.SoftwareConfig.get_by_id(cnxt, config_id)
|
||||||
return api.format_software_config(sc)
|
return api.format_software_config(sc)
|
||||||
|
|
||||||
|
def list_software_configs(self, cnxt, limit=None, marker=None,
|
||||||
|
tenant_safe=True):
|
||||||
|
scs = software_config_object.SoftwareConfig.get_all(
|
||||||
|
cnxt,
|
||||||
|
limit=limit,
|
||||||
|
marker=marker,
|
||||||
|
tenant_safe=tenant_safe)
|
||||||
|
result = [api.format_software_config(sc, detail=False) for sc in scs]
|
||||||
|
return result
|
||||||
|
|
||||||
def create_software_config(self, cnxt, group, name, config,
|
def create_software_config(self, cnxt, group, name, config,
|
||||||
inputs, outputs, options):
|
inputs, outputs, options):
|
||||||
|
|
||||||
|
@ -56,6 +56,11 @@ class SoftwareConfig(base.VersionedObject,
|
|||||||
return cls._from_db_object(
|
return cls._from_db_object(
|
||||||
context, cls(), db_api.software_config_get(context, config_id))
|
context, cls(), db_api.software_config_get(context, config_id))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_all(cls, context, **kwargs):
|
||||||
|
scs = db_api.software_config_get_all(context, **kwargs)
|
||||||
|
return [cls._from_db_object(context, cls(), sc) for sc in scs]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, context, config_id):
|
def delete(cls, context, config_id):
|
||||||
db_api.software_config_delete(context, config_id)
|
db_api.software_config_delete(context, config_id)
|
||||||
|
@ -30,6 +30,7 @@ class EngineClient(object):
|
|||||||
1.1 - Add support_status argument to list_resource_types()
|
1.1 - Add support_status argument to list_resource_types()
|
||||||
1.4 - Add support for service list
|
1.4 - Add support for service list
|
||||||
1.9 - Add template_type option to generate_template()
|
1.9 - Add template_type option to generate_template()
|
||||||
|
1.10 - Add support for software config list
|
||||||
'''
|
'''
|
||||||
|
|
||||||
BASE_RPC_API_VERSION = '1.0'
|
BASE_RPC_API_VERSION = '1.0'
|
||||||
@ -511,6 +512,15 @@ class EngineClient(object):
|
|||||||
return self.call(cnxt, self.make_msg('show_software_config',
|
return self.call(cnxt, self.make_msg('show_software_config',
|
||||||
config_id=config_id))
|
config_id=config_id))
|
||||||
|
|
||||||
|
def list_software_configs(self, cnxt, limit=None, marker=None,
|
||||||
|
tenant_safe=True):
|
||||||
|
return self.call(cnxt,
|
||||||
|
self.make_msg('list_software_configs',
|
||||||
|
limit=limit,
|
||||||
|
marker=marker,
|
||||||
|
tenant_safe=tenant_safe),
|
||||||
|
version='1.10')
|
||||||
|
|
||||||
def create_software_config(self, cnxt, group, name, config,
|
def create_software_config(self, cnxt, group, name, config,
|
||||||
inputs=None, outputs=None, options=None):
|
inputs=None, outputs=None, options=None):
|
||||||
inputs = inputs or []
|
inputs = inputs or []
|
||||||
|
@ -1030,6 +1030,17 @@ class SqlAlchemyTest(common.HeatTestCase):
|
|||||||
self.ctx,
|
self.ctx,
|
||||||
config_id)
|
config_id)
|
||||||
|
|
||||||
|
def test_software_config_get_all(self):
|
||||||
|
self.assertEqual([], db_api.software_config_get_all(self.ctx))
|
||||||
|
tenant_id = self.ctx.tenant_id
|
||||||
|
software_config = db_api.software_config_create(
|
||||||
|
self.ctx, {'name': 'config_mysql',
|
||||||
|
'tenant': tenant_id})
|
||||||
|
self.assertIsNotNone(software_config)
|
||||||
|
software_configs = db_api.software_config_get_all(self.ctx)
|
||||||
|
self.assertEqual(1, len(software_configs))
|
||||||
|
self.assertEqual(software_config, software_configs[0])
|
||||||
|
|
||||||
def test_software_config_delete(self):
|
def test_software_config_delete(self):
|
||||||
tenant_id = self.ctx.tenant_id
|
tenant_id = self.ctx.tenant_id
|
||||||
config = db_api.software_config_create(
|
config = db_api.software_config_create(
|
||||||
@ -1109,16 +1120,16 @@ class SqlAlchemyTest(common.HeatTestCase):
|
|||||||
values = self._deployment_values()
|
values = self._deployment_values()
|
||||||
deployment = db_api.software_deployment_create(self.ctx, values)
|
deployment = db_api.software_deployment_create(self.ctx, values)
|
||||||
self.assertIsNotNone(deployment)
|
self.assertIsNotNone(deployment)
|
||||||
all = db_api.software_deployment_get_all(self.ctx)
|
deployments = db_api.software_deployment_get_all(self.ctx)
|
||||||
self.assertEqual(1, len(all))
|
self.assertEqual(1, len(deployments))
|
||||||
self.assertEqual(deployment, all[0])
|
self.assertEqual(deployment, deployments[0])
|
||||||
all = db_api.software_deployment_get_all(
|
deployments = db_api.software_deployment_get_all(
|
||||||
self.ctx, server_id=values['server_id'])
|
self.ctx, server_id=values['server_id'])
|
||||||
self.assertEqual(1, len(all))
|
self.assertEqual(1, len(deployments))
|
||||||
self.assertEqual(deployment, all[0])
|
self.assertEqual(deployment, deployments[0])
|
||||||
all = db_api.software_deployment_get_all(
|
deployments = db_api.software_deployment_get_all(
|
||||||
self.ctx, server_id=str(uuid.uuid4()))
|
self.ctx, server_id=str(uuid.uuid4()))
|
||||||
self.assertEqual([], all)
|
self.assertEqual([], deployments)
|
||||||
|
|
||||||
def test_software_deployment_update(self):
|
def test_software_deployment_update(self):
|
||||||
deployment_id = str(uuid.uuid4())
|
deployment_id = str(uuid.uuid4())
|
||||||
|
@ -39,7 +39,7 @@ class ServiceEngineTest(common.HeatTestCase):
|
|||||||
|
|
||||||
def test_make_sure_rpc_version(self):
|
def test_make_sure_rpc_version(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'1.9',
|
'1.10',
|
||||||
service.EngineService.RPC_API_VERSION,
|
service.EngineService.RPC_API_VERSION,
|
||||||
('RPC version is changed, please update this test to new version '
|
('RPC version is changed, please update this test to new version '
|
||||||
'and make sure additional test cases are added for RPC APIs '
|
'and make sure additional test cases are added for RPC APIs '
|
||||||
|
@ -48,6 +48,16 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
|||||||
return self.engine.create_software_config(
|
return self.engine.create_software_config(
|
||||||
self.ctx, group, name, config, inputs, outputs, options)
|
self.ctx, group, name, config, inputs, outputs, options)
|
||||||
|
|
||||||
|
def test_list_software_configs(self):
|
||||||
|
config = self._create_software_config()
|
||||||
|
config_id = config['id']
|
||||||
|
self.assertIsNotNone(config)
|
||||||
|
|
||||||
|
configs = self.engine.list_software_configs(self.ctx)
|
||||||
|
self.assertIsNotNone(configs)
|
||||||
|
config_ids = [x['id'] for x in configs]
|
||||||
|
self.assertIn(config_id, config_ids)
|
||||||
|
|
||||||
def test_show_software_config(self):
|
def test_show_software_config(self):
|
||||||
config_id = str(uuid.uuid4())
|
config_id = str(uuid.uuid4())
|
||||||
|
|
||||||
|
@ -3737,6 +3737,15 @@ class RoutesTest(common.HeatTestCase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def test_software_configs(self):
|
def test_software_configs(self):
|
||||||
|
self.assertRoute(
|
||||||
|
self.m,
|
||||||
|
'/aaaa/software_configs',
|
||||||
|
'GET',
|
||||||
|
'index',
|
||||||
|
'SoftwareConfigController',
|
||||||
|
{
|
||||||
|
'tenant_id': 'aaaa'
|
||||||
|
})
|
||||||
self.assertRoute(
|
self.assertRoute(
|
||||||
self.m,
|
self.m,
|
||||||
'/aaaa/software_configs',
|
'/aaaa/software_configs',
|
||||||
@ -4146,6 +4155,18 @@ class SoftwareConfigControllerTest(ControllerTest, common.HeatTestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
webob.exc.HTTPNotFound, self.controller.default, None)
|
webob.exc.HTTPNotFound, self.controller.default, None)
|
||||||
|
|
||||||
|
@mock.patch.object(policy.Enforcer, 'enforce')
|
||||||
|
def test_index(self, mock_enforce):
|
||||||
|
self._mock_enforce_setup(mock_enforce, 'index')
|
||||||
|
req = self._get('/software_configs')
|
||||||
|
with mock.patch.object(
|
||||||
|
self.controller.rpc_client,
|
||||||
|
'list_software_configs',
|
||||||
|
return_value=[]):
|
||||||
|
resp = self.controller.index(req, tenant_id=self.tenant)
|
||||||
|
self.assertEqual(
|
||||||
|
{'software_configs': []}, resp)
|
||||||
|
|
||||||
@mock.patch.object(policy.Enforcer, 'enforce')
|
@mock.patch.object(policy.Enforcer, 'enforce')
|
||||||
def test_show(self, mock_enforce):
|
def test_show(self, mock_enforce):
|
||||||
self._mock_enforce_setup(mock_enforce, 'show')
|
self._mock_enforce_setup(mock_enforce, 'show')
|
||||||
|
@ -268,6 +268,11 @@ class EngineRpcAPITestCase(common.HeatTestCase):
|
|||||||
self._test_engine_api('set_watch_state', 'call',
|
self._test_engine_api('set_watch_state', 'call',
|
||||||
watch_name='watch1', state="xyz")
|
watch_name='watch1', state="xyz")
|
||||||
|
|
||||||
|
def test_list_software_configs(self):
|
||||||
|
self._test_engine_api('list_software_configs', 'call',
|
||||||
|
limit=mock.ANY, marker=mock.ANY,
|
||||||
|
tenant_safe=mock.ANY)
|
||||||
|
|
||||||
def test_show_software_config(self):
|
def test_show_software_config(self):
|
||||||
self._test_engine_api('show_software_config', 'call',
|
self._test_engine_api('show_software_config', 'call',
|
||||||
config_id='cda89008-6ea6-4057-b83d-ccde8f0b48c9')
|
config_id='cda89008-6ea6-4057-b83d-ccde8f0b48c9')
|
||||||
|
Loading…
Reference in New Issue
Block a user