Remove the heat tests

This commit removes the heat tests from tempest, we've been pushing for
these to become a plugin for a long time without any progress. In
addition the heat team has no desire to maintain these tests. [1] Since
they're not providing value anymore let's just delete them. Note, the
clients are not removed in this patch because other projects depend on
those and we shouldn't break those users. Ideally those interfaces
should be moved to lib and just left there.

[1] http://lists.openstack.org/pipermail/openstack-dev/2017-May/116170.html

Depends-On: I983de842f1bf84a939cbcda6c65185c694a69949
Change-Id: Ifc2cac575919da4e361eaa3234d7e0f3e2f98d21
This commit is contained in:
Matthew Treinish 2017-05-02 12:13:45 -04:00
parent ee1108b15a
commit 909891d613
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
24 changed files with 4 additions and 1689 deletions

View File

@ -0,0 +1,4 @@
---
upgrade:
- The Heat API tests have been removed from tempest, they were unmaintained.
The future direction of api test for heat is their in-tree Gabbi tests

View File

@ -1,169 +0,0 @@
# 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 os.path
import yaml
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
import tempest.test
CONF = config.CONF
class BaseOrchestrationTest(tempest.test.BaseTestCase):
"""Base test case class for all Orchestration API tests."""
credentials = ['primary']
@classmethod
def skip_checks(cls):
super(BaseOrchestrationTest, cls).skip_checks()
if not CONF.service_available.heat:
raise cls.skipException("Heat support is required")
@classmethod
def setup_credentials(cls):
super(BaseOrchestrationTest, cls).setup_credentials()
stack_owner_role = CONF.orchestration.stack_owner_role
cls.os = cls.get_client_manager(roles=[stack_owner_role])
@classmethod
def setup_clients(cls):
super(BaseOrchestrationTest, cls).setup_clients()
cls.orchestration_client = cls.os_primary.orchestration_client
cls.client = cls.orchestration_client
cls.servers_client = cls.os_primary.servers_client
cls.keypairs_client = cls.os_primary.keypairs_client
cls.networks_client = cls.os_primary.networks_client
cls.images_v2_client = cls.os_primary.image_client_v2
cls.volumes_client = cls.os_primary.volumes_v2_client
@classmethod
def resource_setup(cls):
super(BaseOrchestrationTest, cls).resource_setup()
cls.build_timeout = CONF.orchestration.build_timeout
cls.build_interval = CONF.orchestration.build_interval
cls.stacks = []
cls.keypairs = []
cls.images = []
@classmethod
def create_stack(cls, stack_name, template_data, parameters=None,
environment=None, files=None):
if parameters is None:
parameters = {}
body = cls.client.create_stack(
stack_name,
template=template_data,
parameters=parameters,
environment=environment,
files=files)
stack_id = body.response['location'].split('/')[-1]
stack_identifier = '%s/%s' % (stack_name, stack_id)
cls.stacks.append(stack_identifier)
return stack_identifier
@classmethod
def _clear_stacks(cls):
for stack_identifier in cls.stacks:
test_utils.call_and_ignore_notfound_exc(
cls.client.delete_stack, stack_identifier)
for stack_identifier in cls.stacks:
test_utils.call_and_ignore_notfound_exc(
cls.client.wait_for_stack_status, stack_identifier,
'DELETE_COMPLETE')
@classmethod
def _create_keypair(cls, name_start='keypair-heat-'):
kp_name = data_utils.rand_name(name_start)
body = cls.keypairs_client.create_keypair(name=kp_name)['keypair']
cls.keypairs.append(kp_name)
return body
@classmethod
def _clear_keypairs(cls):
for kp_name in cls.keypairs:
try:
cls.keypairs_client.delete_keypair(kp_name)
except Exception:
pass
@classmethod
def _create_image(cls, name_start='image-heat-', container_format='bare',
disk_format='iso'):
image_name = data_utils.rand_name(name_start)
body = cls.images_v2_client.create_image(image_name,
container_format,
disk_format)
image_id = body['id']
cls.images.append(image_id)
return body
@classmethod
def _clear_images(cls):
for image_id in cls.images:
test_utils.call_and_ignore_notfound_exc(
cls.images_v2_client.delete_image, image_id)
@classmethod
def read_template(cls, name, ext='yaml'):
loc = ["stacks", "templates", "%s.%s" % (name, ext)]
fullpath = os.path.join(os.path.dirname(__file__), *loc)
with open(fullpath, "r") as f:
content = f.read()
return content
@classmethod
def load_template(cls, name, ext='yaml'):
loc = ["stacks", "templates", "%s.%s" % (name, ext)]
fullpath = os.path.join(os.path.dirname(__file__), *loc)
with open(fullpath, "r") as f:
return yaml.safe_load(f)
@classmethod
def resource_cleanup(cls):
cls._clear_stacks()
cls._clear_keypairs()
cls._clear_images()
super(BaseOrchestrationTest, cls).resource_cleanup()
@staticmethod
def stack_output(stack, output_key):
"""Return a stack output value for a given key."""
return next((o['output_value'] for o in stack['outputs']
if o['output_key'] == output_key), None)
def assert_fields_in_dict(self, obj, *fields):
for field in fields:
self.assertIn(field, obj)
def list_resources(self, stack_identifier):
"""Get a dict mapping of resource names to types."""
resources = self.client.list_resources(stack_identifier)['resources']
self.assertIsInstance(resources, list)
for res in resources:
self.assert_fields_in_dict(res, 'logical_resource_id',
'resource_type', 'resource_status',
'updated_time')
return dict((r['resource_name'], r['resource_type'])
for r in resources)
def get_stack_output(self, stack_identifier, output_key):
body = self.client.show_stack(stack_identifier)['stack']
return self.stack_output(body, output_key)

View File

@ -1,33 +0,0 @@
heat_template_version: 2013-05-23
parameters:
volume_size:
type: number
default: 1
resources:
volume:
type: OS::Cinder::Volume
properties:
size: { get_param: volume_size }
description: a descriptive description
name: volume_name
outputs:
status:
description: status
value: { get_attr: ['volume', 'status'] }
size:
description: size
value: { get_attr: ['volume', 'size'] }
display_description:
description: display_description
value: { get_attr: ['volume', 'display_description'] }
display_name:
value: { get_attr: ['volume', 'display_name'] }
volume_id:
value: { get_resource: volume }

View File

@ -1,34 +0,0 @@
heat_template_version: 2013-05-23
parameters:
volume_size:
type: number
default: 1
resources:
volume:
deletion_policy: 'Retain'
type: OS::Cinder::Volume
properties:
size: { get_param: volume_size }
description: a descriptive description
name: volume_name
outputs:
status:
description: status
value: { get_attr: ['volume', 'status'] }
size:
description: size
value: { get_attr: ['volume', 'size'] }
display_description:
description: display_description
value: { get_attr: ['volume', 'display_description'] }
display_name:
value: { get_attr: ['volume', 'display_name'] }
volume_id:
value: { get_resource: volume }

View File

@ -1,72 +0,0 @@
heat_template_version: '2013-05-23'
description: |
Template which creates single EC2 instance
parameters:
KeyName:
type: string
InstanceType:
type: string
ImageId:
type: string
SubNetCidr:
type: string
ExternalNetworkId:
type: string
DNSServers:
type: comma_delimited_list
timeout:
type: number
resources:
Network:
type: OS::Neutron::Net
properties:
name: NewNetwork
Subnet:
type: OS::Neutron::Subnet
properties:
network_id: {Ref: Network}
name: NewSubnet
ip_version: 4
cidr: { get_param: SubNetCidr }
dns_nameservers: { get_param: DNSServers }
Router:
type: OS::Neutron::Router
properties:
name: NewRouter
admin_state_up: true
external_gateway_info:
network: {get_param: ExternalNetworkId}
RouterInterface:
type: OS::Neutron::RouterInterface
properties:
router_id: {get_resource: Router}
subnet_id: {get_resource: Subnet}
Server:
type: OS::Nova::Server
metadata:
Name: SmokeServerNeutron
properties:
image: {get_param: ImageId}
flavor: {get_param: InstanceType}
key_name: {get_param: KeyName}
networks:
- network: {get_resource: Network}
user_data_format: RAW
user_data:
str_replace:
template: |
#!/bin/sh -v
SIGNAL_DATA='{"Status": "SUCCESS", "Reason": "SmokeServerNeutron created", "Data": "Application has completed configuration.", "UniqueId": "00000"}'
while ! curl --insecure --fail -X PUT -H 'Content-Type:' --data-binary "$SIGNAL_DATA" \
'wait_handle' ; do sleep 3; done
params:
wait_handle: {get_resource: WaitHandleNeutron}
WaitHandleNeutron:
type: AWS::CloudFormation::WaitConditionHandle
WaitCondition:
type: AWS::CloudFormation::WaitCondition
depends_on: Server
properties:
Handle: {get_resource: WaitHandleNeutron}
Timeout: {get_param: timeout}

View File

@ -1,36 +0,0 @@
HeatTemplateFormatVersion: '2012-12-12'
Description: |
Template which creates some simple resources
Parameters:
trigger:
Type: String
Default: not_yet
image:
Type: String
flavor:
Type: String
Resources:
fluffy:
Type: AWS::AutoScaling::LaunchConfiguration
Metadata:
kittens:
- Tom
- Stinky
Properties:
ImageId: {Ref: image}
InstanceType: {Ref: flavor}
UserData:
Fn::Replace:
- variable_a: {Ref: trigger}
variable_b: bee
- |
A == variable_a
B == variable_b
Outputs:
fluffy:
Description: "fluffies irc nick"
Value:
Fn::Replace:
- nick: {Ref: fluffy}
- |
#nick

View File

@ -1,48 +0,0 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template which create two key pairs.",
"Parameters" : {
"KeyPairName1": {
"Type": "String",
"Default": "testkey1"
},
"KeyPairName2": {
"Type": "String",
"Default": "testkey2"
}
},
"Resources" : {
"KeyPairSavePrivate": {
"Type": "OS::Nova::KeyPair",
"Properties": {
"name" : { "Ref" : "KeyPairName1" },
"save_private_key": true
}
},
"KeyPairDontSavePrivate": {
"Type": "OS::Nova::KeyPair",
"Properties": {
"name" : { "Ref" : "KeyPairName2" },
"save_private_key": false
}
}
},
"Outputs": {
"KeyPair_PublicKey": {
"Description": "Public Key of generated keypair.",
"Value": { "Fn::GetAtt" : ["KeyPairSavePrivate", "public_key"] }
},
"KeyPair_PrivateKey": {
"Description": "Private Key of generated keypair.",
"Value": { "Fn::GetAtt" : ["KeyPairSavePrivate", "private_key"] }
},
"KeyPairDontSavePrivate_PublicKey": {
"Description": "Public Key of generated keypair.",
"Value": { "Fn::GetAtt" : ["KeyPairDontSavePrivate", "public_key"] }
},
"KeyPairDontSavePrivate_PrivateKey": {
"Description": "Private Key of generated keypair.",
"Value": { "Fn::GetAtt" : ["KeyPairDontSavePrivate", "private_key"] }
}
}
}

View File

@ -1,43 +0,0 @@
heat_template_version: 2013-05-23
description: >
Template which creates two key pairs.
parameters:
KeyPairName1:
type: string
default: testkey
KeyPairName2:
type: string
default: testkey2
resources:
KeyPairSavePrivate:
type: OS::Nova::KeyPair
properties:
name: { get_param: KeyPairName1 }
save_private_key: true
KeyPairDontSavePrivate:
type: OS::Nova::KeyPair
properties:
name: { get_param: KeyPairName2 }
save_private_key: false
outputs:
KeyPair_PublicKey:
description: Public Key of generated keypair
value: { get_attr: [KeyPairSavePrivate, public_key] }
KeyPair_PrivateKey:
description: Private Key of generated keypair
value: { get_attr: [KeyPairSavePrivate, private_key] }
KeyPairDontSavePrivate_PublicKey:
description: Public Key of generated keypair
value: { get_attr: [KeyPairDontSavePrivate, public_key] }
KeyPairDontSavePrivate_PrivateKey:
description: Private Key of generated keypair
value: { get_attr: [KeyPairDontSavePrivate, private_key] }

View File

@ -1,18 +0,0 @@
heat_template_version: 2013-05-23
parameters:
random_length:
type: number
default: 10
resources:
random:
type: OS::Heat::RandomString
properties:
length: {get_param: random_length}
outputs:
random_length:
value: {get_param: random_length}
random_value:
value: {get_attr: [random, value]}

View File

@ -1,23 +0,0 @@
heat_template_version: 2013-05-23
description: Template which creates a Swift container resource
resources:
SwiftContainerWebsite:
deletion_policy: "Delete"
type: OS::Swift::Container
properties:
X-Container-Read: ".r:*"
X-Container-Meta:
web-index: "index.html"
web-error: "error.html"
SwiftContainer:
type: OS::Swift::Container
outputs:
WebsiteURL:
description: "URL for website hosted on S3"
value: { get_attr: [SwiftContainer, WebsiteURL] }
DomainName:
description: "Domain of Swift host"
value: { get_attr: [SwiftContainer, DomainName] }

View File

@ -1,92 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
class StackEnvironmentTest(base.BaseOrchestrationTest):
@decorators.idempotent_id('37d4346b-1abd-4442-b7b1-2a4e5749a1e3')
def test_environment_parameter(self):
"""Test passing a stack parameter via the environment."""
stack_name = data_utils.rand_name('heat')
template = self.read_template('random_string')
environment = {'parameters': {'random_length': 20}}
stack_identifier = self.create_stack(stack_name, template,
environment=environment)
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
random_len = self.get_stack_output(stack_identifier, 'random_length')
self.assertEqual(20, random_len)
random_value = self.get_stack_output(stack_identifier, 'random_value')
self.assertEqual(20, len(random_value))
@decorators.idempotent_id('73bce717-ad22-4853-bbef-6ed89b632701')
def test_environment_provider_resource(self):
"""Test passing resource_registry defining a provider resource."""
stack_name = data_utils.rand_name('heat')
template = '''
heat_template_version: 2013-05-23
resources:
random:
type: My:Random::String
outputs:
random_value:
value: {get_attr: [random, random_value]}
'''
environment = {'resource_registry':
{'My:Random::String': 'my_random.yaml'}}
files = {'my_random.yaml': self.read_template('random_string')}
stack_identifier = self.create_stack(stack_name, template,
environment=environment,
files=files)
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# random_string.yaml specifies a length of 10
random_value = self.get_stack_output(stack_identifier, 'random_value')
random_string_template = self.load_template('random_string')
expected_length = random_string_template['parameters'][
'random_length']['default']
self.assertEqual(expected_length, len(random_value))
@decorators.idempotent_id('9d682e5a-f4bb-47d5-8472-9d3cacb855df')
def test_files_provider_resource(self):
"""Test untyped defining of a provider resource via "files"."""
# It's also possible to specify the filename directly in the template.
# without adding the type alias to resource_registry
stack_name = data_utils.rand_name('heat')
template = '''
heat_template_version: 2013-05-23
resources:
random:
type: my_random.yaml
outputs:
random_value:
value: {get_attr: [random, random_value]}
'''
files = {'my_random.yaml': self.read_template('random_string')}
stack_identifier = self.create_stack(stack_name, template,
files=files)
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# random_string.yaml specifies a length of 10
random_value = self.get_stack_output(stack_identifier, 'random_value')
random_string_template = self.load_template('random_string')
expected_length = random_string_template['parameters'][
'random_length']['default']
self.assertEqual(expected_length, len(random_value))

View File

@ -1,49 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
CONF = config.CONF
class TestServerStackLimits(base.BaseOrchestrationTest):
@decorators.idempotent_id('ec9bed71-c460-45c9-ab98-295caa9fd76b')
def test_exceed_max_template_size_fails(self):
stack_name = data_utils.rand_name('heat')
fill = 'A' * CONF.orchestration.max_template_size
template = '''
HeatTemplateFormatVersion: '2012-12-12'
Description: '%s'
Outputs:
Foo: bar''' % fill
ex = self.assertRaises(lib_exc.BadRequest, self.create_stack,
stack_name, template)
self.assertIn('exceeds maximum allowed size', str(ex))
@decorators.idempotent_id('d1b83e73-7cad-4a22-9839-036548c5387c')
def test_exceed_max_resources_per_stack(self):
stack_name = data_utils.rand_name('heat')
# Create a big template, one resource more than the limit
template = 'heat_template_version: \'2013-05-23\'\nresources:\n'
rsrc_snippet = ' random%s:\n type: \'OS::Heat::RandomString\'\n'
num_resources = CONF.orchestration.max_resources_per_stack + 1
for i in range(num_resources):
template += rsrc_snippet % i
ex = self.assertRaises(lib_exc.BadRequest, self.create_stack,
stack_name, template)
self.assertIn('Maximum resources per stack exceeded', str(ex))

View File

@ -1,196 +0,0 @@
# 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 netaddr
from oslo_log import log as logging
from tempest.api.orchestration import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions
from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
class NeutronResourcesTestJSON(base.BaseOrchestrationTest):
@classmethod
def skip_checks(cls):
super(NeutronResourcesTestJSON, cls).skip_checks()
if not CONF.service_available.neutron:
raise cls.skipException("Neutron support is required")
@classmethod
def setup_credentials(cls):
cls.set_network_resources()
super(NeutronResourcesTestJSON, cls).setup_credentials()
@classmethod
def setup_clients(cls):
super(NeutronResourcesTestJSON, cls).setup_clients()
cls.subnets_client = cls.os_primary.subnets_client
cls.ports_client = cls.os_primary.ports_client
cls.routers_client = cls.os_primary.routers_client
@classmethod
def resource_setup(cls):
super(NeutronResourcesTestJSON, cls).resource_setup()
cls.neutron_basic_template = cls.load_template('neutron_basic')
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('neutron_basic')
cls.keypair_name = (CONF.orchestration.keypair_name or
cls._create_keypair()['name'])
cls.external_network_id = CONF.network.public_network_id
tenant_cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
mask_bits = CONF.network.project_network_mask_bits
cls.subnet_cidr = tenant_cidr.subnet(mask_bits).next()
# create the stack
cls.stack_identifier = cls.create_stack(
cls.stack_name,
template,
parameters={
'KeyName': cls.keypair_name,
'InstanceType': CONF.orchestration.instance_type,
'ImageId': CONF.compute.image_ref,
'ExternalNetworkId': cls.external_network_id,
'timeout': CONF.orchestration.build_timeout,
'DNSServers': CONF.network.dns_servers,
'SubNetCidr': str(cls.subnet_cidr)
})
cls.stack_id = cls.stack_identifier.split('/')[1]
try:
cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
resources = (cls.client.list_resources(cls.stack_identifier)
['resources'])
except exceptions.TimeoutException:
if CONF.compute_feature_enabled.console_output:
# attempt to log the server console to help with debugging
# the cause of the server not signalling the waitcondition
# to heat.
body = cls.client.show_resource(cls.stack_identifier,
'Server')
server_id = body.get('physical_resource_id')
if server_id:
LOG.debug('Console output for %s', server_id)
output = cls.servers_client.get_console_output(
server_id)['output']
LOG.debug(output)
else:
LOG.debug('Server resource is %s', body)
raise # original exception
cls.test_resources = {}
for resource in resources:
cls.test_resources[resource['logical_resource_id']] = resource
@decorators.idempotent_id('f9e2664c-bc44-4eef-98b6-495e4f9d74b3')
def test_created_resources(self):
"""Verifies created neutron resources."""
resources = [('Network', self.neutron_basic_template['resources'][
'Network']['type']),
('Subnet', self.neutron_basic_template['resources'][
'Subnet']['type']),
('RouterInterface', self.neutron_basic_template[
'resources']['RouterInterface']['type']),
('Server', self.neutron_basic_template['resources'][
'Server']['type'])]
for resource_name, resource_type in resources:
resource = self.test_resources.get(resource_name, None)
self.assertIsInstance(resource, dict)
self.assertEqual(resource_name, resource['logical_resource_id'])
self.assertEqual(resource_type, resource['resource_type'])
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
@decorators.idempotent_id('c572b915-edb1-4e90-b196-c7199a6848c0')
@test.services('network')
def test_created_network(self):
"""Verifies created network."""
network_id = self.test_resources.get('Network')['physical_resource_id']
body = self.networks_client.show_network(network_id)
network = body['network']
self.assertIsInstance(network, dict)
self.assertEqual(network_id, network['id'])
self.assertEqual(self.neutron_basic_template['resources'][
'Network']['properties']['name'], network['name'])
@decorators.idempotent_id('e8f84b96-f9d7-4684-ad5f-340203e9f2c2')
@test.services('network')
def test_created_subnet(self):
"""Verifies created subnet."""
subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
body = self.subnets_client.show_subnet(subnet_id)
subnet = body['subnet']
network_id = self.test_resources.get('Network')['physical_resource_id']
self.assertEqual(subnet_id, subnet['id'])
self.assertEqual(network_id, subnet['network_id'])
self.assertEqual(self.neutron_basic_template['resources'][
'Subnet']['properties']['name'], subnet['name'])
self.assertEqual(sorted(CONF.network.dns_servers),
sorted(subnet['dns_nameservers']))
self.assertEqual(self.neutron_basic_template['resources'][
'Subnet']['properties']['ip_version'], subnet['ip_version'])
self.assertEqual(str(self.subnet_cidr), subnet['cidr'])
@decorators.idempotent_id('96af4c7f-5069-44bc-bdcf-c0390f8a67d1')
@test.services('network')
def test_created_router(self):
"""Verifies created router."""
router_id = self.test_resources.get('Router')['physical_resource_id']
body = self.routers_client.show_router(router_id)
router = body['router']
self.assertEqual(self.neutron_basic_template['resources'][
'Router']['properties']['name'], router['name'])
self.assertEqual(self.external_network_id,
router['external_gateway_info']['network_id'])
self.assertEqual(True, router['admin_state_up'])
@decorators.idempotent_id('89f605bd-153e-43ee-a0ed-9919b63423c5')
@test.services('network')
def test_created_router_interface(self):
"""Verifies created router interface."""
router_id = self.test_resources.get('Router')['physical_resource_id']
network_id = self.test_resources.get('Network')['physical_resource_id']
subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
body = self.ports_client.list_ports()
ports = body['ports']
router_ports = filter(lambda port: port['device_id'] ==
router_id, ports)
created_network_ports = filter(lambda port: port['network_id'] ==
network_id, router_ports)
self.assertEqual(1, len(created_network_ports))
router_interface = created_network_ports[0]
fixed_ips = router_interface['fixed_ips']
subnet_fixed_ips = filter(lambda port: port['subnet_id'] ==
subnet_id, fixed_ips)
self.assertEqual(1, len(subnet_fixed_ips))
router_interface_ip = subnet_fixed_ips[0]['ip_address']
self.assertEqual(str(self.subnet_cidr.iter_hosts().next()),
router_interface_ip)
@decorators.idempotent_id('75d85316-4ac2-4c0e-a1a9-edd2148fc10e')
@test.services('compute', 'network')
def test_created_server(self):
"""Verifies created sever."""
server_id = self.test_resources.get('Server')['physical_resource_id']
server = self.servers_client.show_server(server_id)['server']
self.assertEqual(self.keypair_name, server['key_name'])
self.assertEqual('ACTIVE', server['status'])
network = server['addresses'][self.neutron_basic_template['resources'][
'Network']['properties']['name']][0]
self.assertEqual(4, network['version'])
self.assertIn(netaddr.IPAddress(network['addr']), self.subnet_cidr)

View File

@ -1,150 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
CONF = config.CONF
class StacksTestJSON(base.BaseOrchestrationTest):
@classmethod
def resource_setup(cls):
super(StacksTestJSON, cls).resource_setup()
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('non_empty_stack')
image_id = (CONF.compute.image_ref or
cls._create_image()['id'])
flavor = CONF.orchestration.instance_type
# create the stack
cls.stack_identifier = cls.create_stack(
cls.stack_name,
template,
parameters={
'trigger': 'start',
'image': image_id,
'flavor': flavor
})
cls.stack_id = cls.stack_identifier.split('/')[1]
cls.resource_name = 'fluffy'
cls.resource_type = 'AWS::AutoScaling::LaunchConfiguration'
cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
def _list_stacks(self, expected_num=None, **filter_kwargs):
stacks = self.client.list_stacks(params=filter_kwargs)['stacks']
self.assertIsInstance(stacks, list)
if expected_num is not None:
self.assertEqual(expected_num, len(stacks))
return stacks
@decorators.idempotent_id('065c652a-720d-4760-9132-06aedeb8e3ab')
def test_stack_list(self):
"""Created stack should be in the list of existing stacks."""
stacks = self._list_stacks()
stacks_names = map(lambda stack: stack['stack_name'], stacks)
self.assertIn(self.stack_name, stacks_names)
@decorators.idempotent_id('992f96e3-41ee-4ff6-91c7-bcfb670c0919')
def test_stack_show(self):
"""Getting details about created stack should be possible."""
stack = self.client.show_stack(self.stack_name)['stack']
self.assertIsInstance(stack, dict)
self.assert_fields_in_dict(stack, 'stack_name', 'id', 'links',
'parameters', 'outputs', 'disable_rollback',
'stack_status_reason', 'stack_status',
'creation_time', 'updated_time',
'capabilities', 'notification_topics',
'timeout_mins', 'template_description')
self.assert_fields_in_dict(stack['parameters'], 'AWS::StackId',
'trigger', 'AWS::Region', 'AWS::StackName')
self.assertEqual(True, stack['disable_rollback'],
'disable_rollback should default to True')
self.assertEqual(self.stack_name, stack['stack_name'])
self.assertEqual(self.stack_id, stack['id'])
self.assertEqual('fluffy', stack['outputs'][0]['output_key'])
@decorators.idempotent_id('fe719f7a-305a-44d8-bbb5-c91e93d9da17')
def test_suspend_resume_stack(self):
"""Suspend and resume a stack."""
self.client.suspend_stack(self.stack_identifier)
self.client.wait_for_stack_status(self.stack_identifier,
'SUSPEND_COMPLETE')
self.client.resume_stack(self.stack_identifier)
self.client.wait_for_stack_status(self.stack_identifier,
'RESUME_COMPLETE')
@decorators.idempotent_id('c951d55e-7cce-4c1f-83a0-bad735437fa6')
def test_list_resources(self):
"""Get list of created resources for the stack should be possible."""
resources = self.list_resources(self.stack_identifier)
self.assertEqual({self.resource_name: self.resource_type}, resources)
@decorators.idempotent_id('2aba03b3-392f-4237-900b-1f5a5e9bd962')
def test_show_resource(self):
"""Getting details about created resource should be possible."""
resource = self.client.show_resource(self.stack_identifier,
self.resource_name)['resource']
self.assertIsInstance(resource, dict)
self.assert_fields_in_dict(resource, 'resource_name', 'description',
'links', 'logical_resource_id',
'resource_status', 'updated_time',
'required_by', 'resource_status_reason',
'physical_resource_id', 'resource_type')
self.assertEqual(self.resource_name, resource['logical_resource_id'])
self.assertEqual(self.resource_type, resource['resource_type'])
@decorators.idempotent_id('898070a9-eba5-4fae-b7d6-cf3ffa03090f')
def test_resource_metadata(self):
"""Getting metadata for created resources should be possible."""
metadata = self.client.show_resource_metadata(
self.stack_identifier,
self.resource_name)['metadata']
self.assertIsInstance(metadata, dict)
self.assertEqual(['Tom', 'Stinky'], metadata.get('kittens', None))
@decorators.idempotent_id('46567533-0a7f-483b-8942-fa19e0f17839')
def test_list_events(self):
"""Getting list of created events for the stack should be possible."""
events = self.client.list_events(self.stack_identifier)['events']
self.assertIsInstance(events, list)
for event in events:
self.assert_fields_in_dict(event, 'logical_resource_id', 'id',
'resource_status_reason',
'resource_status', 'event_time')
resource_statuses = [event['resource_status'] for event in events]
self.assertIn('CREATE_IN_PROGRESS', resource_statuses)
self.assertIn('CREATE_COMPLETE', resource_statuses)
@decorators.idempotent_id('92465723-1673-400a-909d-4773757a3f21')
def test_show_event(self):
"""Getting details about an event should be possible."""
events = self.client.list_resource_events(self.stack_identifier,
self.resource_name)['events']
self.assertNotEqual([], events)
events.sort(key=lambda event: event['event_time'])
event_id = events[0]['id']
event = self.client.show_event(self.stack_identifier,
self.resource_name, event_id)['event']
self.assertIsInstance(event, dict)
self.assert_fields_in_dict(event, 'resource_name', 'event_time',
'links', 'logical_resource_id',
'resource_status', 'resource_status_reason',
'physical_resource_id', 'id',
'resource_properties', 'resource_type')
self.assertEqual(self.resource_name, event['resource_name'])
self.assertEqual('state changed', event['resource_status_reason'])
self.assertEqual(self.resource_name, event['logical_resource_id'])

View File

@ -1,92 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
class NovaKeyPairResourcesYAMLTest(base.BaseOrchestrationTest):
_tpl_type = 'yaml'
_resource = 'resources'
_type = 'type'
@classmethod
def resource_setup(cls):
super(NovaKeyPairResourcesYAMLTest, cls).resource_setup()
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('nova_keypair', ext=cls._tpl_type)
# create the stack, avoid any duplicated key.
cls.stack_identifier = cls.create_stack(
cls.stack_name,
template,
parameters={
'KeyPairName1': cls.stack_name + '_1',
'KeyPairName2': cls.stack_name + '_2'
})
cls.stack_id = cls.stack_identifier.split('/')[1]
cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
resources = (cls.client.list_resources(cls.stack_identifier)
['resources'])
cls.test_resources = {}
for resource in resources:
cls.test_resources[resource['logical_resource_id']] = resource
@decorators.idempotent_id('b476eac2-a302-4815-961f-18c410a2a537')
def test_created_resources(self):
"""Verifies created keypair resource."""
nova_keypair_template = self.load_template('nova_keypair',
ext=self._tpl_type)
resources = [('KeyPairSavePrivate',
nova_keypair_template[self._resource][
'KeyPairSavePrivate'][self._type]),
('KeyPairDontSavePrivate',
nova_keypair_template[self._resource][
'KeyPairDontSavePrivate'][self._type])]
for resource_name, resource_type in resources:
resource = self.test_resources.get(resource_name, None)
self.assertIsInstance(resource, dict)
self.assertEqual(resource_name, resource['logical_resource_id'])
self.assertEqual(resource_type, resource['resource_type'])
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
@decorators.idempotent_id('8d77dec7-91fd-45a6-943d-5abd45e338a4')
def test_stack_keypairs_output(self):
stack = self.client.show_stack(self.stack_name)['stack']
self.assertIsInstance(stack, dict)
output_map = {}
for outputs in stack['outputs']:
output_map[outputs['output_key']] = outputs['output_value']
# Test that first key generated public and private keys
self.assertIn('KeyPair_PublicKey', output_map)
self.assertIn("Generated", output_map['KeyPair_PublicKey'])
self.assertIn('KeyPair_PrivateKey', output_map)
self.assertIn('-----BEGIN', output_map['KeyPair_PrivateKey'])
# Test that second key generated public key, and private key is not
# in the output due to save_private_key = false
self.assertIn('KeyPairDontSavePrivate_PublicKey', output_map)
self.assertIn('Generated',
output_map['KeyPairDontSavePrivate_PublicKey'])
self.assertIn(u'KeyPairDontSavePrivate_PrivateKey', output_map)
private_key = output_map['KeyPairDontSavePrivate_PrivateKey']
self.assertEqual(0, len(private_key))
class NovaKeyPairResourcesAWSTest(NovaKeyPairResourcesYAMLTest):
_tpl_type = 'json'
_resource = 'Resources'
_type = 'Type'

View File

@ -1,49 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib import decorators
class ResourceTypesTest(base.BaseOrchestrationTest):
@decorators.attr(type='smoke')
@decorators.idempotent_id('7123d082-3577-4a30-8f00-f805327c4ffd')
def test_resource_type_list(self):
"""Verify it is possible to list resource types."""
resource_types = self.client.list_resource_types()['resource_types']
self.assertIsInstance(resource_types, list)
self.assertIn('OS::Nova::Server', resource_types)
@decorators.attr(type='smoke')
@decorators.idempotent_id('0e85a483-828b-4a28-a0e3-f0a21809192b')
def test_resource_type_show(self):
"""Verify it is possible to get schema about resource types."""
resource_types = self.client.list_resource_types()['resource_types']
self.assertNotEmpty(resource_types)
for resource_type in resource_types:
type_schema = self.client.show_resource_type(resource_type)
self.assert_fields_in_dict(type_schema, 'properties',
'attributes', 'resource_type')
self.assertEqual(resource_type, type_schema['resource_type'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('8401821d-65fe-4d43-9fa3-57d5ce3a35c7')
def test_resource_type_template(self):
"""Verify it is possible to get template about resource types."""
type_template = self.client.show_resource_type_template(
'OS::Nova::Server')
self.assert_fields_in_dict(
type_template,
'Outputs',
'Parameters', 'Resources')

View File

@ -1,169 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
class TestSoftwareConfig(base.BaseOrchestrationTest):
def setUp(self):
super(TestSoftwareConfig, self).setUp()
self.configs = []
# Add 2 sets of software configuration
self.configs.append(self._config_create('a'))
self.configs.append(self._config_create('b'))
# Create a deployment using config a's id
self._deployment_create(self.configs[0]['id'])
def _config_create(self, suffix):
configuration = {'group': 'script',
'inputs': [],
'outputs': [],
'options': {}}
configuration['name'] = 'heat_soft_config_%s' % suffix
configuration['config'] = '#!/bin/bash echo init-%s' % suffix
api_config = self.client.create_software_config(**configuration)
configuration['id'] = api_config['software_config']['id']
self.addCleanup(self._config_delete, configuration['id'])
self._validate_config(configuration, api_config)
return configuration
def _validate_config(self, configuration, api_config):
# Assert all expected keys are present with matching data
for k in configuration:
self.assertEqual(configuration[k],
api_config['software_config'][k])
def _deployment_create(self, config_id):
self.server_id = data_utils.rand_name('dummy-server')
self.action = 'ACTION_0'
self.status = 'STATUS_0'
self.input_values = {}
self.output_values = []
self.status_reason = 'REASON_0'
self.signal_transport = 'NO_SIGNAL'
self.deployment = self.client.create_software_deploy(
self.server_id, config_id, self.action, self.status,
self.input_values, self.output_values, self.status_reason,
self.signal_transport)
self.deployment_id = self.deployment['software_deployment']['id']
self.addCleanup(self._deployment_delete, self.deployment_id)
def _deployment_delete(self, deploy_id):
self.client.delete_software_deploy(deploy_id)
# Testing that it is really gone
self.assertRaises(
lib_exc.NotFound, self.client.show_software_deployment,
self.deployment_id)
def _config_delete(self, config_id):
self.client.delete_software_config(config_id)
# Testing that it is really gone
self.assertRaises(
lib_exc.NotFound, self.client.show_software_config, config_id)
@decorators.attr(type='smoke')
@decorators.idempotent_id('136162ed-9445-4b9c-b7fc-306af8b5da99')
def test_get_software_config(self):
"""Testing software config get."""
for conf in self.configs:
api_config = self.client.show_software_config(conf['id'])
self._validate_config(conf, api_config)
@decorators.attr(type='smoke')
@decorators.idempotent_id('1275c835-c967-4a2c-8d5d-ad533447ed91')
def test_get_deployment_list(self):
"""Getting a list of all deployments"""
deploy_list = self.client.list_software_deployments()
deploy_ids = [deploy['id'] for deploy in
deploy_list['software_deployments']]
self.assertIn(self.deployment_id, deploy_ids)
@decorators.attr(type='smoke')
@decorators.idempotent_id('fe7cd9f9-54b1-429c-a3b7-7df8451db913')
def test_get_deployment_metadata(self):
"""Testing deployment metadata get"""
metadata = self.client.show_software_deployment_metadata(
self.server_id)
conf_ids = [conf['id'] for conf in metadata['metadata']]
self.assertIn(self.configs[0]['id'], conf_ids)
def _validate_deployment(self, action, status, reason, config_id):
deployment = self.client.show_software_deployment(self.deployment_id)
self.assertEqual(action, deployment['software_deployment']['action'])
self.assertEqual(status, deployment['software_deployment']['status'])
self.assertEqual(reason,
deployment['software_deployment']['status_reason'])
self.assertEqual(config_id,
deployment['software_deployment']['config_id'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('f29d21f3-ed75-47cf-8cdc-ef1bdeb4c674')
def test_software_deployment_create_validate(self):
"""Testing software deployment was created as expected."""
# Asserting that all fields were created
self.assert_fields_in_dict(
self.deployment['software_deployment'], 'action', 'config_id',
'id', 'input_values', 'output_values', 'server_id', 'status',
'status_reason')
# Testing get for this deployment and verifying parameters
self._validate_deployment(self.action, self.status,
self.status_reason, self.configs[0]['id'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('2ac43ab3-34f2-415d-be2e-eabb4d14ee32')
def test_software_deployment_update_no_metadata_change(self):
"""Testing software deployment update without metadata change."""
metadata = self.client.show_software_deployment_metadata(
self.server_id)
# Updating values without changing the configuration ID
new_action = 'ACTION_1'
new_status = 'STATUS_1'
new_reason = 'REASON_1'
self.client.update_software_deploy(
self.deployment_id, self.server_id, self.configs[0]['id'],
new_action, new_status, self.input_values, self.output_values,
new_reason, self.signal_transport)
# Verifying get and that the deployment was updated as expected
self._validate_deployment(new_action, new_status,
new_reason, self.configs[0]['id'])
# Metadata should not be changed at this point
test_metadata = self.client.show_software_deployment_metadata(
self.server_id)
for key in metadata['metadata'][0]:
self.assertEqual(
metadata['metadata'][0][key],
test_metadata['metadata'][0][key])
@decorators.attr(type='smoke')
@decorators.idempotent_id('92c48944-d79d-4595-a840-8e1a581c1a72')
def test_software_deployment_update_with_metadata_change(self):
"""Testing software deployment update with metadata change."""
metadata = self.client.show_software_deployment_metadata(
self.server_id)
self.client.update_software_deploy(
self.deployment_id, self.server_id, self.configs[1]['id'],
self.action, self.status, self.input_values,
self.output_values, self.status_reason, self.signal_transport)
self._validate_deployment(self.action, self.status,
self.status_reason, self.configs[1]['id'])
# Metadata should now be changed
new_metadata = self.client.show_software_deployment_metadata(
self.server_id)
# Its enough to test the ID in this case
meta_id = metadata['metadata'][0]['id']
test_id = new_metadata['metadata'][0]['id']
self.assertNotEqual(meta_id, test_id)

View File

@ -1,59 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
class StacksTestJSON(base.BaseOrchestrationTest):
empty_template = "HeatTemplateFormatVersion: '2012-12-12'\n"
@decorators.attr(type='smoke')
@decorators.idempotent_id('d35d628c-07f6-4674-85a1-74db9919e986')
def test_stack_list_responds(self):
stacks = self.client.list_stacks()['stacks']
self.assertIsInstance(stacks, list)
@decorators.attr(type='smoke')
@decorators.idempotent_id('10498bd5-a83e-4b62-a817-ce24afe938fe')
def test_stack_crud_no_resources(self):
stack_name = data_utils.rand_name('heat')
# create the stack
stack_identifier = self.create_stack(
stack_name, self.empty_template)
stack_id = stack_identifier.split('/')[1]
# wait for create complete (with no resources it should be instant)
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# check for stack in list
stacks = self.client.list_stacks()['stacks']
list_ids = list([stack['id'] for stack in stacks])
self.assertIn(stack_id, list_ids)
# fetch the stack
stack = self.client.show_stack(stack_identifier)['stack']
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
# fetch the stack by name
stack = self.client.show_stack(stack_name)['stack']
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
# fetch the stack by id
stack = self.client.show_stack(stack_id)['stack']
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
# delete the stack
self.client.delete_stack(stack_identifier)
self.client.wait_for_stack_status(stack_identifier, 'DELETE_COMPLETE')

View File

@ -1,120 +0,0 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# 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 tempest.api.orchestration import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest import test
CONF = config.CONF
class SwiftResourcesTestJSON(base.BaseOrchestrationTest):
@classmethod
def skip_checks(cls):
super(SwiftResourcesTestJSON, cls).skip_checks()
if not CONF.service_available.swift:
raise cls.skipException("Swift support is required")
@classmethod
def setup_credentials(cls):
super(SwiftResourcesTestJSON, cls).setup_credentials()
stack_owner_role = CONF.orchestration.stack_owner_role
operator_role = CONF.object_storage.operator_role
cls.os = cls.get_client_manager(
roles=[stack_owner_role, operator_role])
@classmethod
def setup_clients(cls):
super(SwiftResourcesTestJSON, cls).setup_clients()
cls.account_client = cls.os_primary.account_client
cls.container_client = cls.os_primary.container_client
@classmethod
def resource_setup(cls):
super(SwiftResourcesTestJSON, cls).resource_setup()
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('swift_basic')
# create the stack
cls.stack_identifier = cls.create_stack(
cls.stack_name,
template)
cls.stack_id = cls.stack_identifier.split('/')[1]
cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
cls.test_resources = {}
resources = (cls.client.list_resources(cls.stack_identifier)
['resources'])
for resource in resources:
cls.test_resources[resource['logical_resource_id']] = resource
@decorators.idempotent_id('1a6fe69e-4be4-4990-9a7a-84b6f18019cb')
def test_created_resources(self):
"""Created stack should be in the list of existing stacks."""
swift_basic_template = self.load_template('swift_basic')
resources = [('SwiftContainer', swift_basic_template['resources'][
'SwiftContainer']['type']),
('SwiftContainerWebsite', swift_basic_template[
'resources']['SwiftContainerWebsite']['type'])]
for resource_name, resource_type in resources:
resource = self.test_resources.get(resource_name)
self.assertIsInstance(resource, dict)
self.assertEqual(resource_type, resource['resource_type'])
self.assertEqual(resource_name, resource['logical_resource_id'])
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
@decorators.idempotent_id('bd438b18-5494-4d5a-9ce6-d2a942ec5060')
@test.services('object_storage')
def test_created_containers(self):
params = {'format': 'json'}
_, container_list = \
self.account_client.list_account_containers(params=params)
created_containers = [cont for cont in container_list
if cont['name'].startswith(self.stack_name)]
self.assertEqual(2, len(created_containers))
@decorators.idempotent_id('73d0c093-9922-44a0-8b1d-1fc092dee367')
@test.services('object_storage')
def test_acl(self):
acl_headers = ('x-container-meta-web-index', 'x-container-read')
swcont = self.test_resources.get(
'SwiftContainer')['physical_resource_id']
swcont_website = self.test_resources.get(
'SwiftContainerWebsite')['physical_resource_id']
headers, _ = self.container_client.list_container_metadata(swcont)
for h in acl_headers:
self.assertNotIn(h, headers)
headers, _ = self.container_client.list_container_metadata(
swcont_website)
for h in acl_headers:
self.assertIn(h, headers)
@decorators.idempotent_id('fda06135-6777-4594-aefa-0f6107169698')
@test.services('object_storage')
def test_metadata(self):
swift_basic_template = self.load_template('swift_basic')
metadatas = swift_basic_template['resources']['SwiftContainerWebsite'][
'properties']['X-Container-Meta']
swcont_website = self.test_resources.get(
'SwiftContainerWebsite')['physical_resource_id']
headers, _ = self.container_client.list_container_metadata(
swcont_website)
for meta in metadatas:
header_meta = "x-container-meta-%s" % meta
self.assertIn(header_meta, headers)
self.assertEqual(headers[header_meta], metadatas[meta])

View File

@ -1,61 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
class TemplateYAMLTestJSON(base.BaseOrchestrationTest):
template = """
HeatTemplateFormatVersion: '2012-12-12'
Description: |
Template which creates only a new user
Resources:
CfnUser:
Type: AWS::IAM::User
"""
@classmethod
def resource_setup(cls):
super(TemplateYAMLTestJSON, cls).resource_setup()
cls.stack_name = data_utils.rand_name('heat')
cls.stack_identifier = cls.create_stack(cls.stack_name, cls.template)
cls.client.wait_for_stack_status(cls.stack_identifier,
'CREATE_COMPLETE')
cls.stack_id = cls.stack_identifier.split('/')[1]
cls.parameters = {}
@decorators.idempotent_id('47430699-c368-495e-a1db-64c26fd967d7')
def test_show_template(self):
"""Getting template used to create the stack."""
self.client.show_template(self.stack_identifier)
@decorators.idempotent_id('ed53debe-8727-46c5-ab58-eba6090ec4de')
def test_validate_template(self):
"""Validating template passing it content."""
self.client.validate_template(self.template,
self.parameters)
class TemplateAWSTestJSON(TemplateYAMLTestJSON):
template = """
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template which creates only a new user",
"Resources" : {
"CfnUser" : {
"Type" : "AWS::IAM::User"
}
}
}
"""

View File

@ -1,60 +0,0 @@
# Copyright 2014 NEC 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.
from tempest.api.orchestration import base
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
class TemplateYAMLNegativeTestJSON(base.BaseOrchestrationTest):
template = """
HeatTemplateFormatVersion: '2012-12-12'
Description: |
Template which creates only a new user
Resources:
CfnUser:
Type: AWS::IAM::User
"""
invalid_template_url = 'http:///template.yaml'
@classmethod
def resource_setup(cls):
super(TemplateYAMLNegativeTestJSON, cls).resource_setup()
cls.parameters = {}
@decorators.attr(type=['negative'])
@decorators.idempotent_id('5586cbca-ddc4-4152-9db8-fa1ce5fc1876')
def test_validate_template_url(self):
"""Validating template passing url to it."""
self.assertRaises(lib_exc.BadRequest,
self.client.validate_template_url,
template_url=self.invalid_template_url,
parameters=self.parameters)
class TemplateAWSNegativeTestJSON(TemplateYAMLNegativeTestJSON):
template = """
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Template which creates only a new user",
"Resources" : {
"CfnUser" : {
"Type" : "AWS::IAM::User"
}
}
}
"""
invalid_template_url = 'http:///template.template'

View File

@ -1,116 +0,0 @@
# 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 tempest.api.orchestration import base
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from tempest import test
CONF = config.CONF
class CinderResourcesTest(base.BaseOrchestrationTest):
@classmethod
def skip_checks(cls):
super(CinderResourcesTest, cls).skip_checks()
if not CONF.service_available.cinder:
raise cls.skipException('Cinder support is required')
def _cinder_verify(self, volume_id, template):
self.assertIsNotNone(volume_id)
volume = self.volumes_client.show_volume(volume_id)['volume']
self.assertEqual('available', volume.get('status'))
self.assertEqual(CONF.volume.volume_size, volume.get('size'))
self.assertEqual(template['resources']['volume']['properties'][
'description'], volume.get('description'))
self.assertEqual(template['resources']['volume']['properties'][
'name'], volume.get('name'))
def _outputs_verify(self, stack_identifier, template):
self.assertEqual('available',
self.get_stack_output(stack_identifier, 'status'))
self.assertEqual(str(CONF.volume.volume_size),
self.get_stack_output(stack_identifier, 'size'))
self.assertEqual(template['resources']['volume']['properties'][
'description'], self.get_stack_output(stack_identifier,
'display_description'))
self.assertEqual(template['resources']['volume']['properties'][
'name'], self.get_stack_output(stack_identifier, 'display_name'))
@decorators.idempotent_id('c3243329-7bdd-4730-b402-4d19d50c41d8')
@test.services('volume')
def test_cinder_volume_create_delete(self):
"""Create and delete a volume via OS::Cinder::Volume."""
stack_name = data_utils.rand_name('heat')
template = self.read_template('cinder_basic')
stack_identifier = self.create_stack(
stack_name,
template,
parameters={
'volume_size': CONF.volume.volume_size
})
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# Verify with cinder that the volume exists, with matching details
volume_id = self.get_stack_output(stack_identifier, 'volume_id')
cinder_basic_template = self.load_template('cinder_basic')
self._cinder_verify(volume_id, cinder_basic_template)
# Verify the stack outputs are as expected
self._outputs_verify(stack_identifier, cinder_basic_template)
# Delete the stack and ensure the volume is gone
self.client.delete_stack(stack_identifier)
self.client.wait_for_stack_status(stack_identifier, 'DELETE_COMPLETE')
self.assertRaises(lib_exc.NotFound,
self.volumes_client.show_volume,
volume_id)
def _cleanup_volume(self, volume_id):
"""Cleanup the volume direct with cinder."""
self.volumes_client.delete_volume(volume_id)
self.volumes_client.wait_for_resource_deletion(volume_id)
@decorators.idempotent_id('ea8b3a46-b932-4c18-907a-fe23f00b33f8')
@test.services('volume')
def test_cinder_volume_create_delete_retain(self):
"""Ensure the 'Retain' deletion policy is respected."""
stack_name = data_utils.rand_name('heat')
template = self.read_template('cinder_basic_delete_retain')
stack_identifier = self.create_stack(
stack_name,
template,
parameters={
'volume_size': CONF.volume.volume_size
})
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# Verify with cinder that the volume exists, with matching details
volume_id = self.get_stack_output(stack_identifier, 'volume_id')
self.addCleanup(self._cleanup_volume, volume_id)
retain_template = self.load_template('cinder_basic_delete_retain')
self._cinder_verify(volume_id, retain_template)
# Verify the stack outputs are as expected
self._outputs_verify(stack_identifier, retain_template)
# Delete the stack and ensure the volume is *not* gone
self.client.delete_stack(stack_identifier)
self.client.wait_for_stack_status(stack_identifier, 'DELETE_COMPLETE')
self._cinder_verify(volume_id, retain_template)
# Volume cleanup happens via addCleanup calling _cleanup_volume