Add ability to filter stacks by tag
blueprint stack-tags Change-Id: I4b5bc741fc271cb08ec588ae962573c59286dae5
This commit is contained in:
parent
ce3f1d299c
commit
3c30bf8727
@ -186,6 +186,10 @@ class StackController(object):
|
||||
'show_deleted': 'single',
|
||||
'show_nested': 'single',
|
||||
'show_hidden': 'single',
|
||||
'tags': 'single',
|
||||
'tags_any': 'single',
|
||||
'not_tags': 'single',
|
||||
'not_tags_any': 'single',
|
||||
}
|
||||
params = util.get_allowed_params(req.params, whitelist)
|
||||
filter_params = util.get_allowed_params(req.params, filter_whitelist)
|
||||
@ -212,6 +216,30 @@ class StackController(object):
|
||||
params[rpc_api.PARAM_SHOW_HIDDEN])
|
||||
show_hidden = params[rpc_api.PARAM_SHOW_HIDDEN]
|
||||
|
||||
tags = None
|
||||
if rpc_api.PARAM_TAGS in params:
|
||||
params[rpc_api.PARAM_TAGS] = param_utils.extract_tags(
|
||||
params[rpc_api.PARAM_TAGS])
|
||||
tags = params[rpc_api.PARAM_TAGS]
|
||||
|
||||
tags_any = None
|
||||
if rpc_api.PARAM_TAGS_ANY in params:
|
||||
params[rpc_api.PARAM_TAGS_ANY] = param_utils.extract_tags(
|
||||
params[rpc_api.PARAM_TAGS_ANY])
|
||||
tags_any = params[rpc_api.PARAM_TAGS_ANY]
|
||||
|
||||
not_tags = None
|
||||
if rpc_api.PARAM_NOT_TAGS in params:
|
||||
params[rpc_api.PARAM_NOT_TAGS] = param_utils.extract_tags(
|
||||
params[rpc_api.PARAM_NOT_TAGS])
|
||||
not_tags = params[rpc_api.PARAM_NOT_TAGS]
|
||||
|
||||
not_tags_any = None
|
||||
if rpc_api.PARAM_NOT_TAGS_ANY in params:
|
||||
params[rpc_api.PARAM_NOT_TAGS_ANY] = param_utils.extract_tags(
|
||||
params[rpc_api.PARAM_NOT_TAGS_ANY])
|
||||
not_tags_any = params[rpc_api.PARAM_NOT_TAGS_ANY]
|
||||
|
||||
# get the with_count value, if invalid, raise ValueError
|
||||
with_count = False
|
||||
if req.params.get('with_count'):
|
||||
@ -236,7 +264,11 @@ class StackController(object):
|
||||
tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden,
|
||||
tags=tags,
|
||||
tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
except AttributeError as exc:
|
||||
LOG.warn(_LW("Old Engine Version: %s") % exc)
|
||||
|
||||
|
@ -53,3 +53,12 @@ def extract_int(name, value, allow_zero=True, allow_negative=False):
|
||||
{'name': name, 'value': value})
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def extract_tags(subject):
|
||||
tags = subject.split(',')
|
||||
for tag in tags:
|
||||
if len(tag) > 80:
|
||||
raise ValueError(_('Invalid tag, "%s" is longer than 80 '
|
||||
'characters') % tag)
|
||||
return tags
|
||||
|
@ -142,10 +142,13 @@ def stack_get_by_name(context, stack_name):
|
||||
|
||||
def stack_get_all(context, limit=None, sort_keys=None, marker=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
return IMPL.stack_get_all(context, limit, sort_keys,
|
||||
marker, sort_dir, filters, tenant_safe,
|
||||
show_deleted, show_nested, show_hidden)
|
||||
show_deleted, show_nested, show_hidden,
|
||||
tags, tags_any, not_tags, not_tags_any)
|
||||
|
||||
|
||||
def stack_get_all_by_owner_id(context, owner_id):
|
||||
@ -153,12 +156,18 @@ def stack_get_all_by_owner_id(context, owner_id):
|
||||
|
||||
|
||||
def stack_count_all(context, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
return IMPL.stack_count_all(context, filters=filters,
|
||||
tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden,
|
||||
tags=tags,
|
||||
tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
|
||||
|
||||
def stack_create(context, values):
|
||||
|
@ -23,6 +23,7 @@ import osprofiler.sqlalchemy
|
||||
import six
|
||||
import sqlalchemy
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.orm import aliased as orm_aliased
|
||||
from sqlalchemy.orm import session as orm_session
|
||||
|
||||
from heat.common import crypt
|
||||
@ -399,7 +400,8 @@ def _paginate_query(context, query, model, limit=None, sort_keys=None,
|
||||
|
||||
|
||||
def _query_stack_get_all(context, tenant_safe=True, show_deleted=False,
|
||||
show_nested=False, show_hidden=False):
|
||||
show_nested=False, show_hidden=False, tags=None,
|
||||
tags_any=None, not_tags=None, not_tags_any=None):
|
||||
if show_nested:
|
||||
query = soft_delete_aware_query(
|
||||
context, models.Stack, show_deleted=show_deleted
|
||||
@ -412,6 +414,33 @@ def _query_stack_get_all(context, tenant_safe=True, show_deleted=False,
|
||||
if tenant_safe:
|
||||
query = query.filter_by(tenant=context.tenant_id)
|
||||
|
||||
if tags:
|
||||
for tag in tags:
|
||||
tag_alias = orm_aliased(models.StackTag)
|
||||
query = query.join(tag_alias, models.Stack.tags)
|
||||
query = query.filter(tag_alias.tag == tag)
|
||||
|
||||
if tags_any:
|
||||
query = query.filter(
|
||||
models.Stack.tags.any(
|
||||
models.StackTag.tag.in_(tags_any)))
|
||||
|
||||
if not_tags:
|
||||
subquery = soft_delete_aware_query(
|
||||
context, models.Stack, show_deleted=show_deleted
|
||||
)
|
||||
for tag in not_tags:
|
||||
tag_alias = orm_aliased(models.StackTag)
|
||||
subquery = subquery.join(tag_alias, models.Stack.tags)
|
||||
subquery = subquery.filter(tag_alias.tag == tag)
|
||||
not_stack_ids = [s.id for s in subquery.all()]
|
||||
query = query.filter(models.Stack.id.notin_(not_stack_ids))
|
||||
|
||||
if not_tags_any:
|
||||
query = query.filter(
|
||||
~models.Stack.tags.any(
|
||||
models.StackTag.tag.in_(not_tags_any)))
|
||||
|
||||
if not show_hidden:
|
||||
query = query.filter(
|
||||
~models.Stack.tags.any(
|
||||
@ -422,11 +451,15 @@ def _query_stack_get_all(context, tenant_safe=True, show_deleted=False,
|
||||
|
||||
def stack_get_all(context, limit=None, sort_keys=None, marker=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
query = _query_stack_get_all(context, tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden, tags=tags,
|
||||
tags_any=tags_any, not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
return _filter_and_page_query(context, query, limit, sort_keys,
|
||||
marker, sort_dir, filters).all()
|
||||
|
||||
@ -448,11 +481,15 @@ def _filter_and_page_query(context, query, limit=None, sort_keys=None,
|
||||
|
||||
|
||||
def stack_count_all(context, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
query = _query_stack_get_all(context, tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden, tags=tags,
|
||||
tags_any=tags_any, not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
query = db_filters.exact_filter(query, models.Stack, filters)
|
||||
return query.count()
|
||||
|
||||
|
@ -266,7 +266,7 @@ class EngineService(service.Service):
|
||||
by the RPC caller.
|
||||
"""
|
||||
|
||||
RPC_API_VERSION = '1.7'
|
||||
RPC_API_VERSION = '1.8'
|
||||
|
||||
def __init__(self, host, topic, manager=None):
|
||||
super(EngineService, self).__init__()
|
||||
@ -467,7 +467,9 @@ class EngineService(service.Service):
|
||||
@context.request_context
|
||||
def list_stacks(self, cnxt, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
"""
|
||||
The list_stacks method returns attributes of all stacks. It supports
|
||||
pagination (``limit`` and ``marker``), sorting (``sort_keys`` and
|
||||
@ -483,18 +485,31 @@ class EngineService(service.Service):
|
||||
:param show_deleted: if true, show soft-deleted stacks
|
||||
:param show_nested: if true, show nested stacks
|
||||
:param show_hidden: if true, show hidden stacks
|
||||
:param tags: show stacks containing these tags, combine multiple
|
||||
tags using the boolean AND expression
|
||||
:param tags_any: show stacks containing these tags, combine multiple
|
||||
tags using the boolean OR expression
|
||||
:param not_tags: show stacks not containing these tags, combine
|
||||
multiple tags using the boolean AND expression
|
||||
:param not_tags_any: show stacks not containing these tags, combine
|
||||
multiple tags using the boolean OR expression
|
||||
:returns: a list of formatted stacks
|
||||
"""
|
||||
stacks = parser.Stack.load_all(cnxt, limit, marker, sort_keys,
|
||||
sort_dir, filters, tenant_safe,
|
||||
show_deleted, resolve_data=False,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden,
|
||||
tags=tags, tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
return [api.format_stack(stack) for stack in stacks]
|
||||
|
||||
@context.request_context
|
||||
def count_stacks(self, cnxt, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
"""
|
||||
Return the number of stacks that match the given filters
|
||||
:param cnxt: RPC context.
|
||||
@ -502,7 +517,15 @@ class EngineService(service.Service):
|
||||
:param tenant_safe: if true, scope the request by the current tenant
|
||||
:param show_deleted: if true, count will include the deleted stacks
|
||||
:param show_nested: if true, count will include nested stacks
|
||||
:param show_hidden: if true, show hidden stacks
|
||||
:param show_hidden: if true, count will include hidden stacks
|
||||
:param tags: count stacks containing these tags, combine multiple tags
|
||||
using the boolean AND expression
|
||||
:param tags_any: count stacks containing these tags, combine multiple
|
||||
tags using the boolean OR expression
|
||||
:param not_tags: count stacks not containing these tags, combine
|
||||
multiple tags using the boolean AND expression
|
||||
:param not_tags_any: count stacks not containing these tags, combine
|
||||
multiple tags using the boolean OR expression
|
||||
:returns: a integer representing the number of matched stacks
|
||||
"""
|
||||
return stack_object.Stack.count_all(
|
||||
@ -511,7 +534,11 @@ class EngineService(service.Service):
|
||||
tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden)
|
||||
show_hidden=show_hidden,
|
||||
tags=tags,
|
||||
tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any)
|
||||
|
||||
def _validate_deferred_auth_context(self, cnxt, stack):
|
||||
if cfg.CONF.deferred_auth_method != 'password':
|
||||
|
@ -354,7 +354,8 @@ class Stack(collections.Mapping):
|
||||
def load_all(cls, context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, resolve_data=True,
|
||||
show_nested=False, show_hidden=False):
|
||||
show_nested=False, show_hidden=False, tags=None,
|
||||
tags_any=None, not_tags=None, not_tags_any=None):
|
||||
stacks = stack_object.Stack.get_all(
|
||||
context,
|
||||
limit,
|
||||
@ -365,7 +366,11 @@ class Stack(collections.Mapping):
|
||||
tenant_safe,
|
||||
show_deleted,
|
||||
show_nested,
|
||||
show_hidden) or []
|
||||
show_hidden,
|
||||
tags,
|
||||
tags_any,
|
||||
not_tags,
|
||||
not_tags_any) or []
|
||||
for stack in stacks:
|
||||
yield cls._from_db(context, stack, resolve_data=resolve_data)
|
||||
|
||||
|
@ -18,12 +18,14 @@ PARAM_KEYS = (
|
||||
PARAM_TIMEOUT, PARAM_DISABLE_ROLLBACK, PARAM_ADOPT_STACK_DATA,
|
||||
PARAM_SHOW_DELETED, PARAM_SHOW_NESTED, PARAM_EXISTING,
|
||||
PARAM_CLEAR_PARAMETERS, PARAM_GLOBAL_TENANT, PARAM_LIMIT,
|
||||
PARAM_NESTED_DEPTH, PARAM_TAGS, PARAM_SHOW_HIDDEN
|
||||
PARAM_NESTED_DEPTH, PARAM_TAGS, PARAM_SHOW_HIDDEN, PARAM_TAGS_ANY,
|
||||
PARAM_NOT_TAGS, PARAM_NOT_TAGS_ANY
|
||||
) = (
|
||||
'timeout_mins', 'disable_rollback', 'adopt_stack_data',
|
||||
'show_deleted', 'show_nested', 'existing',
|
||||
'clear_parameters', 'global_tenant', 'limit',
|
||||
'nested_depth', 'tags', 'show_hidden'
|
||||
'nested_depth', 'tags', 'show_hidden', 'tags_any',
|
||||
'not_tags', 'not_tags_any'
|
||||
)
|
||||
|
||||
STACK_KEYS = (
|
||||
|
@ -91,7 +91,9 @@ class EngineClient(object):
|
||||
|
||||
def list_stacks(self, ctxt, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
"""
|
||||
The list_stacks method returns attributes of all stacks. It supports
|
||||
pagination (``limit`` and ``marker``), sorting (``sort_keys`` and
|
||||
@ -107,6 +109,14 @@ class EngineClient(object):
|
||||
:param show_deleted: if true, show soft-deleted stacks
|
||||
:param show_nested: if true, show nested stacks
|
||||
:param show_hidden: if true, show hidden stacks
|
||||
:param tags: show stacks containing these tags, combine multiple
|
||||
tags using the boolean AND expression
|
||||
:param tags_any: show stacks containing these tags, combine multiple
|
||||
tags using the boolean OR expression
|
||||
:param not_tags: show stacks not containing these tags, combine
|
||||
multiple tags using the boolean AND expression
|
||||
:param not_tags_any: show stacks not containing these tags, combine
|
||||
multiple tags using the boolean OR expression
|
||||
:returns: a list of stacks
|
||||
"""
|
||||
return self.call(ctxt,
|
||||
@ -116,10 +126,16 @@ class EngineClient(object):
|
||||
tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden))
|
||||
show_hidden=show_hidden,
|
||||
tags=tags, tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any),
|
||||
version='1.8')
|
||||
|
||||
def count_stacks(self, ctxt, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False, show_hidden=False):
|
||||
show_deleted=False, show_nested=False, show_hidden=False,
|
||||
tags=None, tags_any=None, not_tags=None,
|
||||
not_tags_any=None):
|
||||
"""
|
||||
Return the number of stacks that match the given filters
|
||||
:param ctxt: RPC context.
|
||||
@ -127,7 +143,15 @@ class EngineClient(object):
|
||||
:param tenant_safe: if true, scope the request by the current tenant
|
||||
:param show_deleted: if true, count will include the deleted stacks
|
||||
:param show_nested: if true, count will include nested stacks
|
||||
:param show_hidden: if true, show hidden stacks
|
||||
:param show_hidden: if true, count will include hidden stacks
|
||||
:param tags: count stacks containing these tags, combine multiple tags
|
||||
using the boolean AND expression
|
||||
:param tags_any: count stacks containing these tags, combine multiple
|
||||
tags using the boolean OR expression
|
||||
:param not_tags: count stacks not containing these tags, combine
|
||||
multiple tags using the boolean AND expression
|
||||
:param not_tags_any: count stacks not containing these tags, combine
|
||||
multiple tags using the boolean OR expression
|
||||
:returns: a integer representing the number of matched stacks
|
||||
"""
|
||||
return self.call(ctxt, self.make_msg('count_stacks',
|
||||
@ -135,7 +159,12 @@ class EngineClient(object):
|
||||
tenant_safe=tenant_safe,
|
||||
show_deleted=show_deleted,
|
||||
show_nested=show_nested,
|
||||
show_hidden=show_hidden))
|
||||
show_hidden=show_hidden,
|
||||
tags=tags,
|
||||
tags_any=tags_any,
|
||||
not_tags=not_tags,
|
||||
not_tags_any=not_tags_any),
|
||||
version='1.8')
|
||||
|
||||
def show_stack(self, ctxt, stack_identity):
|
||||
"""
|
||||
@ -205,7 +234,7 @@ class EngineClient(object):
|
||||
user_creds_id=user_creds_id,
|
||||
stack_user_project_id=stack_user_project_id,
|
||||
parent_resource_name=parent_resource_name),
|
||||
version='1.7')
|
||||
version='1.8')
|
||||
|
||||
def update_stack(self, ctxt, stack_identity, template, params,
|
||||
files, args):
|
||||
|
@ -574,6 +574,113 @@ class SqlAlchemyTest(common.HeatTestCase):
|
||||
for stack in st_db_visible:
|
||||
self.assertNotEqual(stacks[0].id, stack.id)
|
||||
|
||||
def test_stack_get_all_by_tags(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag1', 'tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag1', 'tag2', 'tag3']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag2'])
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1', 'tag2'])
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1', 'tag2', 'tag3'])
|
||||
self.assertEqual(1, len(st_db))
|
||||
|
||||
def test_stack_get_all_by_tags_any(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag2']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag1', 'tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag1', 'tag3']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags_any=['tag1'])
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags_any=['tag1', 'tag2',
|
||||
'tag3'])
|
||||
self.assertEqual(3, len(st_db))
|
||||
|
||||
def test_stack_get_all_by_not_tags(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag1', 'tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag1', 'tag2', 'tag3']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, not_tags=['tag2'])
|
||||
self.assertEqual(1, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, not_tags=['tag1', 'tag2'])
|
||||
self.assertEqual(1, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, not_tags=['tag1', 'tag2',
|
||||
'tag3'])
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
def test_stack_get_all_by_not_tags_any(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag2']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag1', 'tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag1', 'tag3']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, not_tags_any=['tag1'])
|
||||
self.assertEqual(1, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, not_tags_any=['tag1', 'tag2',
|
||||
'tag3'])
|
||||
self.assertEqual(0, len(st_db))
|
||||
|
||||
def test_stack_get_all_by_tag_with_pagination(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag1']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1'])
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1'], limit=1)
|
||||
self.assertEqual(1, len(st_db))
|
||||
self.assertEqual(stacks[2].id, st_db[0].id)
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1'], limit=1,
|
||||
marker=stacks[2].id)
|
||||
self.assertEqual(1, len(st_db))
|
||||
self.assertEqual(stacks[0].id, st_db[0].id)
|
||||
|
||||
def test_stack_get_all_by_tag_with_show_hidden(self):
|
||||
cfg.CONF.set_override('hidden_stack_tags', ['hidden'])
|
||||
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['hidden', 'tag1']
|
||||
stacks[1].store()
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1'],
|
||||
show_hidden=True)
|
||||
self.assertEqual(2, len(st_db))
|
||||
|
||||
st_db = db_api.stack_get_all(self.ctx, tags=['tag1'],
|
||||
show_hidden=False)
|
||||
self.assertEqual(1, len(st_db))
|
||||
|
||||
def test_stack_count_all(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
|
||||
@ -609,6 +716,38 @@ class SqlAlchemyTest(common.HeatTestCase):
|
||||
st_db_visible = db_api.stack_count_all(self.ctx, show_hidden=False)
|
||||
self.assertEqual(2, st_db_visible)
|
||||
|
||||
def test_count_all_by_tags(self):
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['tag2']
|
||||
stacks[1].store()
|
||||
stacks[2].tags = ['tag2']
|
||||
stacks[2].store()
|
||||
|
||||
st_db = db_api.stack_count_all(self.ctx, tags=['tag1'])
|
||||
self.assertEqual(1, st_db)
|
||||
|
||||
st_db = db_api.stack_count_all(self.ctx, tags=['tag2'])
|
||||
self.assertEqual(2, st_db)
|
||||
|
||||
def test_count_all_by_tag_with_show_hidden(self):
|
||||
cfg.CONF.set_override('hidden_stack_tags', ['hidden'])
|
||||
|
||||
stacks = [self._setup_test_stack('stack', x)[1] for x in UUIDs]
|
||||
stacks[0].tags = ['tag1']
|
||||
stacks[0].store()
|
||||
stacks[1].tags = ['hidden', 'tag1']
|
||||
stacks[1].store()
|
||||
|
||||
st_db = db_api.stack_count_all(self.ctx, tags=['tag1'],
|
||||
show_hidden=True)
|
||||
self.assertEqual(2, st_db)
|
||||
|
||||
st_db = db_api.stack_count_all(self.ctx, tags=['tag1'],
|
||||
show_hidden=False)
|
||||
self.assertEqual(1, st_db)
|
||||
|
||||
def test_stack_count_all_with_filters(self):
|
||||
self._setup_test_stack('foo', UUID1)
|
||||
self._setup_test_stack('bar', UUID2)
|
||||
|
@ -162,9 +162,11 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
default_args = {'limit': None, 'sort_keys': None, 'marker': None,
|
||||
'sort_dir': None, 'filters': None, 'tenant_safe': True,
|
||||
'show_deleted': False, 'show_nested': False,
|
||||
'show_hidden': False}
|
||||
'show_hidden': False, 'tags': None,
|
||||
'tags_any': None, 'not_tags': None,
|
||||
'not_tags_any': None}
|
||||
mock_call.assert_called_once_with(
|
||||
dummy_req.context, ('list_stacks', default_args))
|
||||
dummy_req.context, ('list_stacks', default_args), version='1.8')
|
||||
|
||||
@mock.patch.object(rpc_client.EngineClient, 'call')
|
||||
def test_list_rmt_aterr(self, mock_call):
|
||||
@ -180,7 +182,7 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
result = self.controller.list(dummy_req)
|
||||
self.assertIsInstance(result, exception.HeatInvalidParameterValueError)
|
||||
mock_call.assert_called_once_with(
|
||||
dummy_req.context, ('list_stacks', mock.ANY))
|
||||
dummy_req.context, ('list_stacks', mock.ANY), version='1.8')
|
||||
|
||||
@mock.patch.object(rpc_client.EngineClient, 'call')
|
||||
def test_list_rmt_interr(self, mock_call):
|
||||
@ -196,7 +198,7 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
result = self.controller.list(dummy_req)
|
||||
self.assertIsInstance(result, exception.HeatInternalFailureError)
|
||||
mock_call.assert_called_once_with(
|
||||
dummy_req.context, ('list_stacks', mock.ANY))
|
||||
dummy_req.context, ('list_stacks', mock.ANY), version='1.8')
|
||||
|
||||
def test_describe_last_updated_time(self):
|
||||
params = {'Action': 'DescribeStacks'}
|
||||
@ -508,7 +510,7 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(failure)
|
||||
|
||||
def _stub_rpc_create_stack_call_success(self, stack_name, engine_parms,
|
||||
@ -536,7 +538,7 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndReturn(engine_resp)
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
@ -386,9 +386,11 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
default_args = {'limit': None, 'sort_keys': None, 'marker': None,
|
||||
'sort_dir': None, 'filters': None, 'tenant_safe': True,
|
||||
'show_deleted': False, 'show_nested': False,
|
||||
'show_hidden': False}
|
||||
'show_hidden': False, 'tags': None,
|
||||
'tags_any': None, 'not_tags': None,
|
||||
'not_tags_any': None}
|
||||
mock_call.assert_called_once_with(
|
||||
req.context, ('list_stacks', default_args))
|
||||
req.context, ('list_stacks', default_args), version='1.8')
|
||||
|
||||
@mock.patch.object(rpc_client.EngineClient, 'call')
|
||||
def test_index_whitelists_pagination_params(self, mock_call, mock_enforce):
|
||||
@ -407,7 +409,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
|
||||
rpc_call_args, _ = mock_call.call_args
|
||||
engine_args = rpc_call_args[1][1]
|
||||
self.assertEqual(9, len(engine_args))
|
||||
self.assertEqual(13, len(engine_args))
|
||||
self.assertIn('limit', engine_args)
|
||||
self.assertIn('sort_keys', engine_args)
|
||||
self.assertIn('marker', engine_args)
|
||||
@ -608,7 +610,11 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
tenant_safe=True,
|
||||
show_deleted=True,
|
||||
show_nested=False,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(rpc_client.EngineClient, 'call')
|
||||
def test_detail(self, mock_call, mock_enforce):
|
||||
@ -667,9 +673,11 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
default_args = {'limit': None, 'sort_keys': None, 'marker': None,
|
||||
'sort_dir': None, 'filters': None, 'tenant_safe': True,
|
||||
'show_deleted': False, 'show_nested': False,
|
||||
'show_hidden': False}
|
||||
'show_hidden': False, 'tags': None,
|
||||
'tags_any': None, 'not_tags': None,
|
||||
'not_tags_any': None}
|
||||
mock_call.assert_called_once_with(
|
||||
req.context, ('list_stacks', default_args))
|
||||
req.context, ('list_stacks', default_args), version='1.8')
|
||||
|
||||
@mock.patch.object(rpc_client.EngineClient, 'call')
|
||||
def test_index_rmt_aterr(self, mock_call, mock_enforce):
|
||||
@ -685,7 +693,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
self.assertEqual(400, resp.json['code'])
|
||||
self.assertEqual('AttributeError', resp.json['error']['type'])
|
||||
mock_call.assert_called_once_with(
|
||||
req.context, ('list_stacks', mock.ANY))
|
||||
req.context, ('list_stacks', mock.ANY), version='1.8')
|
||||
|
||||
def test_index_err_denied_policy(self, mock_enforce):
|
||||
self._mock_enforce_setup(mock_enforce, 'index', False)
|
||||
@ -713,7 +721,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
self.assertEqual(500, resp.json['code'])
|
||||
self.assertEqual('Exception', resp.json['error']['type'])
|
||||
mock_call.assert_called_once_with(
|
||||
req.context, ('list_stacks', mock.ANY))
|
||||
req.context, ('list_stacks', mock.ANY), version='1.8')
|
||||
|
||||
def test_create(self, mock_enforce):
|
||||
self._mock_enforce_setup(mock_enforce, 'create', True)
|
||||
@ -743,7 +751,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndReturn(dict(identity))
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -806,7 +814,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndReturn(dict(identity))
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -893,7 +901,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndReturn(dict(identity))
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -937,7 +945,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(to_remote_error(AttributeError()))
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
@ -954,7 +962,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(to_remote_error(unknown_parameter))
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
@ -971,7 +979,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(to_remote_error(missing_parameter))
|
||||
self.m.ReplayAll()
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
@ -1025,7 +1033,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(to_remote_error(error))
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -1106,7 +1114,7 @@ class StackControllerTest(ControllerTest, common.HeatTestCase):
|
||||
'user_creds_id': None,
|
||||
'parent_resource_name': None,
|
||||
'stack_user_project_id': None}),
|
||||
version='1.7'
|
||||
version='1.8'
|
||||
).AndRaise(to_remote_error(error))
|
||||
self.m.ReplayAll()
|
||||
|
||||
|
@ -88,3 +88,11 @@ class TestExtractInt(common.HeatTestCase):
|
||||
param_utils.extract_int, 'num', 'true')
|
||||
self.assertRaises(ValueError,
|
||||
param_utils.extract_int, 'num', True)
|
||||
|
||||
|
||||
class TestExtractTags(common.HeatTestCase):
|
||||
def test_extract_tags(self):
|
||||
self.assertRaises(ValueError, param_utils.extract_tags, "aaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaa,a")
|
||||
self.assertEqual(["foo", "bar"], param_utils.extract_tags('foo,bar'))
|
||||
|
@ -1736,7 +1736,7 @@ class StackServiceTest(common.HeatTestCase):
|
||||
|
||||
def test_make_sure_rpc_version(self):
|
||||
self.assertEqual(
|
||||
'1.7',
|
||||
'1.8',
|
||||
service.EngineService.RPC_API_VERSION,
|
||||
('RPC version is changed, please update this test to new version '
|
||||
'and make sure additional test cases are added for RPC APIs '
|
||||
@ -2064,6 +2064,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2080,6 +2084,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2095,6 +2103,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2110,6 +2122,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2125,6 +2141,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
True,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2140,6 +2160,10 @@ class StackServiceTest(common.HeatTestCase):
|
||||
True,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
@ -2155,6 +2179,86 @@ class StackServiceTest(common.HeatTestCase):
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
True,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
def test_stack_list_tags(self, mock_stack_get_all):
|
||||
self.eng.list_stacks(self.ctx, tags=['foo', 'bar'])
|
||||
mock_stack_get_all.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
['foo', 'bar'],
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
def test_stack_list_tags_any(self, mock_stack_get_all):
|
||||
self.eng.list_stacks(self.ctx, tags_any=['foo', 'bar'])
|
||||
mock_stack_get_all.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
['foo', 'bar'],
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
def test_stack_list_not_tags(self, mock_stack_get_all):
|
||||
self.eng.list_stacks(self.ctx, not_tags=['foo', 'bar'])
|
||||
mock_stack_get_all.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
['foo', 'bar'],
|
||||
mock.ANY,
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'get_all')
|
||||
def test_stack_list_not_tags_any(self, mock_stack_get_all):
|
||||
self.eng.list_stacks(self.ctx, not_tags_any=['foo', 'bar'])
|
||||
mock_stack_get_all.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
['foo', 'bar'],
|
||||
)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
@ -2165,7 +2269,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=mock.ANY,
|
||||
show_deleted=False,
|
||||
show_nested=False,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
def test_count_stacks_tenant_safe_default_true(self, mock_stack_count_all):
|
||||
@ -2175,7 +2283,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=True,
|
||||
show_deleted=False,
|
||||
show_nested=False,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
def test_count_stacks_passes_tenant_safe_info(self, mock_stack_count_all):
|
||||
@ -2185,7 +2297,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=False,
|
||||
show_deleted=False,
|
||||
show_nested=False,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
def test_count_stacks_show_nested(self, mock_stack_count_all):
|
||||
@ -2195,7 +2311,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=True,
|
||||
show_deleted=False,
|
||||
show_nested=True,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
def test_count_stack_show_deleted(self, mock_stack_count_all):
|
||||
@ -2205,7 +2325,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=True,
|
||||
show_deleted=True,
|
||||
show_nested=False,
|
||||
show_hidden=False)
|
||||
show_hidden=False,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@mock.patch.object(stack_object.Stack, 'count_all')
|
||||
def test_count_stack_show_hidden(self, mock_stack_count_all):
|
||||
@ -2215,7 +2339,11 @@ class StackServiceTest(common.HeatTestCase):
|
||||
tenant_safe=True,
|
||||
show_deleted=False,
|
||||
show_nested=False,
|
||||
show_hidden=True)
|
||||
show_hidden=True,
|
||||
tags=None,
|
||||
tags_any=None,
|
||||
not_tags=None,
|
||||
not_tags_any=None)
|
||||
|
||||
@stack_context('service_abandon_stack')
|
||||
def test_abandon_stack(self):
|
||||
|
@ -116,6 +116,10 @@ class EngineRpcAPITestCase(common.HeatTestCase):
|
||||
'show_deleted': mock.ANY,
|
||||
'show_nested': mock.ANY,
|
||||
'show_hidden': mock.ANY,
|
||||
'tags': mock.ANY,
|
||||
'tags_any': mock.ANY,
|
||||
'not_tags': mock.ANY,
|
||||
'not_tags_any': mock.ANY,
|
||||
}
|
||||
self._test_engine_api('list_stacks', 'call', **default_args)
|
||||
|
||||
@ -126,6 +130,10 @@ class EngineRpcAPITestCase(common.HeatTestCase):
|
||||
'show_deleted': mock.ANY,
|
||||
'show_nested': mock.ANY,
|
||||
'show_hidden': mock.ANY,
|
||||
'tags': mock.ANY,
|
||||
'tags_any': mock.ANY,
|
||||
'not_tags': mock.ANY,
|
||||
'not_tags_any': mock.ANY,
|
||||
}
|
||||
self._test_engine_api('count_stacks', 'call', **default_args)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user