Merge "Remove the heat tests"

This commit is contained in:
Jenkins 2017-05-10 23:11:20 +00:00 committed by Gerrit Code Review
commit 72d54b6877
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