Initial heat orchestration tests.
This does a creat/list/show/delete of a stack with no resources. It should run fast and is suitable for gating, since it doesn't create any nova instances. I'd consider it to be a smoke test. It confirms that heat-api can communicate with heat-engine, and that heat-engine has a properly configured database. Blueprint: add-basic-heat-tests Change-Id: Id249a34c3a28e1e69d9eb000c6c5c2e82d619178
This commit is contained in:
parent
1937d09fb0
commit
d2525a9c5e
|
@ -0,0 +1,110 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# 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 logging
|
||||
import time
|
||||
|
||||
from tempest import clients
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
import tempest.test
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseOrchestrationTest(tempest.test.BaseTestCase):
|
||||
"""Base test case class for all Orchestration API tests."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
os = clients.OrchestrationManager()
|
||||
cls.orchestration_cfg = os.config.orchestration
|
||||
if not cls.orchestration_cfg.heat_available:
|
||||
raise cls.skipException("Heat support is required")
|
||||
|
||||
cls.os = os
|
||||
cls.orchestration_client = os.orchestration_client
|
||||
cls.keypairs_client = os.keypairs_client
|
||||
cls.stacks = []
|
||||
|
||||
@classmethod
|
||||
def _get_identity_admin_client(cls):
|
||||
"""
|
||||
Returns an instance of the Identity Admin API client
|
||||
"""
|
||||
os = clients.AdminManager(interface=cls._interface)
|
||||
admin_client = os.identity_client
|
||||
return admin_client
|
||||
|
||||
@classmethod
|
||||
def _get_client_args(cls):
|
||||
|
||||
return (
|
||||
cls.config,
|
||||
cls.config.identity.admin_username,
|
||||
cls.config.identity.admin_password,
|
||||
cls.config.identity.uri
|
||||
)
|
||||
|
||||
def create_stack(self, stack_name, template_data, parameters={}):
|
||||
resp, body = self.client.create_stack(
|
||||
stack_name,
|
||||
template=template_data,
|
||||
parameters=parameters)
|
||||
self.assertEqual('201', resp['status'])
|
||||
stack_id = resp['location'].split('/')[-1]
|
||||
stack_identifier = '%s/%s' % (stack_name, stack_id)
|
||||
self.stacks.append(stack_identifier)
|
||||
return stack_identifier
|
||||
|
||||
@classmethod
|
||||
def clear_stacks(cls):
|
||||
for stack_identifier in cls.stacks:
|
||||
try:
|
||||
cls.orchestration_client.delete_stack(stack_identifier)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for stack_identifier in cls.stacks:
|
||||
try:
|
||||
cls.orchestration_client.wait_for_stack_status(
|
||||
stack_identifier, 'DELETE_COMPLETE')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _create_keypair(self, namestart='keypair-heat-'):
|
||||
kp_name = rand_name(namestart)
|
||||
resp, body = self.keypairs_client.create_keypair(kp_name)
|
||||
self.assertEqual(body['name'], kp_name)
|
||||
return body
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.clear_stacks()
|
||||
|
||||
def wait_for(self, condition):
|
||||
"""Repeatedly calls condition() until a timeout."""
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
try:
|
||||
condition()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
if int(time.time()) - start_time >= self.build_timeout:
|
||||
condition()
|
||||
return
|
||||
time.sleep(self.build_interval)
|
|
@ -0,0 +1,77 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# 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 logging
|
||||
|
||||
from tempest.api.orchestration import base
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest.test import attr
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StacksTestJSON(base.BaseOrchestrationTest):
|
||||
_interface = 'json'
|
||||
|
||||
empty_template = "HeatTemplateFormatVersion: '2012-12-12'\n"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(StacksTestJSON, cls).setUpClass()
|
||||
cls.client = cls.orchestration_client
|
||||
|
||||
@attr(type='smoke')
|
||||
def test_stack_list_responds(self):
|
||||
resp, body = self.client.list_stacks()
|
||||
stacks = body['stacks']
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(stacks, list)
|
||||
|
||||
@attr(type='smoke')
|
||||
def test_stack_crud_no_resources(self):
|
||||
stack_name = rand_name('heat')
|
||||
|
||||
# count how many stacks to start with
|
||||
resp, body = self.client.list_stacks()
|
||||
stack_count = len(body['stacks'])
|
||||
|
||||
# create the stack
|
||||
stack_identifier = self.create_stack(
|
||||
stack_name, self.empty_template)
|
||||
|
||||
# wait for create complete (with no resources it should be instant)
|
||||
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
|
||||
|
||||
# stack count will increment by 1
|
||||
resp, body = self.client.list_stacks()
|
||||
self.assertEqual(stack_count + 1, len(body['stacks']),
|
||||
'Expected stack count to increment by 1')
|
||||
|
||||
# fetch the stack
|
||||
resp, body = self.client.get_stack(stack_identifier)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
|
||||
# fetch the stack by name
|
||||
resp, body = self.client.get_stack(stack_name)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
|
||||
# fetch the stack by id
|
||||
stack_id = stack_identifier.split('/')[1]
|
||||
resp, body = self.client.get_stack(stack_id)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
|
||||
# delete the stack
|
||||
resp = self.client.delete_stack(stack_identifier)
|
||||
self.assertEqual('204', resp[0]['status'])
|
Loading…
Reference in New Issue