From 909891d61318cdf9d6b98f0d5e15b60ffadebfb3 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 2 May 2017 12:13:45 -0400 Subject: [PATCH] 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 --- .../remove-heat-tests-9efb42cac3e0b306.yaml | 4 + tempest/api/orchestration/__init__.py | 0 tempest/api/orchestration/base.py | 169 --------------- tempest/api/orchestration/stacks/__init__.py | 0 .../stacks/templates/cinder_basic.yaml | 33 --- .../templates/cinder_basic_delete_retain.yaml | 34 --- .../stacks/templates/neutron_basic.yaml | 72 ------- .../stacks/templates/non_empty_stack.yaml | 36 ---- .../stacks/templates/nova_keypair.json | 48 ----- .../stacks/templates/nova_keypair.yaml | 43 ---- .../stacks/templates/random_string.yaml | 18 -- .../stacks/templates/swift_basic.yaml | 23 -- .../orchestration/stacks/test_environment.py | 92 -------- .../api/orchestration/stacks/test_limits.py | 49 ----- .../stacks/test_neutron_resources.py | 196 ------------------ .../stacks/test_non_empty_stack.py | 150 -------------- .../stacks/test_nova_keypair_resources.py | 92 -------- .../stacks/test_resource_types.py | 49 ----- .../orchestration/stacks/test_soft_conf.py | 169 --------------- .../api/orchestration/stacks/test_stacks.py | 59 ------ .../stacks/test_swift_resources.py | 120 ----------- .../orchestration/stacks/test_templates.py | 61 ------ .../stacks/test_templates_negative.py | 60 ------ .../api/orchestration/stacks/test_volumes.py | 116 ----------- 24 files changed, 4 insertions(+), 1689 deletions(-) create mode 100644 releasenotes/notes/remove-heat-tests-9efb42cac3e0b306.yaml delete mode 100644 tempest/api/orchestration/__init__.py delete mode 100644 tempest/api/orchestration/base.py delete mode 100644 tempest/api/orchestration/stacks/__init__.py delete mode 100644 tempest/api/orchestration/stacks/templates/cinder_basic.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/neutron_basic.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/non_empty_stack.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/nova_keypair.json delete mode 100644 tempest/api/orchestration/stacks/templates/nova_keypair.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/random_string.yaml delete mode 100644 tempest/api/orchestration/stacks/templates/swift_basic.yaml delete mode 100644 tempest/api/orchestration/stacks/test_environment.py delete mode 100644 tempest/api/orchestration/stacks/test_limits.py delete mode 100644 tempest/api/orchestration/stacks/test_neutron_resources.py delete mode 100644 tempest/api/orchestration/stacks/test_non_empty_stack.py delete mode 100644 tempest/api/orchestration/stacks/test_nova_keypair_resources.py delete mode 100644 tempest/api/orchestration/stacks/test_resource_types.py delete mode 100644 tempest/api/orchestration/stacks/test_soft_conf.py delete mode 100644 tempest/api/orchestration/stacks/test_stacks.py delete mode 100644 tempest/api/orchestration/stacks/test_swift_resources.py delete mode 100644 tempest/api/orchestration/stacks/test_templates.py delete mode 100644 tempest/api/orchestration/stacks/test_templates_negative.py delete mode 100644 tempest/api/orchestration/stacks/test_volumes.py diff --git a/releasenotes/notes/remove-heat-tests-9efb42cac3e0b306.yaml b/releasenotes/notes/remove-heat-tests-9efb42cac3e0b306.yaml new file mode 100644 index 0000000000..4d0f3ce067 --- /dev/null +++ b/releasenotes/notes/remove-heat-tests-9efb42cac3e0b306.yaml @@ -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 diff --git a/tempest/api/orchestration/__init__.py b/tempest/api/orchestration/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py deleted file mode 100644 index d9d8017872..0000000000 --- a/tempest/api/orchestration/base.py +++ /dev/null @@ -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) diff --git a/tempest/api/orchestration/stacks/__init__.py b/tempest/api/orchestration/stacks/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic.yaml deleted file mode 100644 index 61c271c6c5..0000000000 --- a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml +++ /dev/null @@ -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 } diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml deleted file mode 100644 index 0bc6d69af5..0000000000 --- a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml +++ /dev/null @@ -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 } diff --git a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml b/tempest/api/orchestration/stacks/templates/neutron_basic.yaml deleted file mode 100644 index ccb1b54c9a..0000000000 --- a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml +++ /dev/null @@ -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} diff --git a/tempest/api/orchestration/stacks/templates/non_empty_stack.yaml b/tempest/api/orchestration/stacks/templates/non_empty_stack.yaml deleted file mode 100644 index 4f9df91eab..0000000000 --- a/tempest/api/orchestration/stacks/templates/non_empty_stack.yaml +++ /dev/null @@ -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 diff --git a/tempest/api/orchestration/stacks/templates/nova_keypair.json b/tempest/api/orchestration/stacks/templates/nova_keypair.json deleted file mode 100644 index 63d3817f31..0000000000 --- a/tempest/api/orchestration/stacks/templates/nova_keypair.json +++ /dev/null @@ -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"] } - } - } -} diff --git a/tempest/api/orchestration/stacks/templates/nova_keypair.yaml b/tempest/api/orchestration/stacks/templates/nova_keypair.yaml deleted file mode 100644 index 81ad99c805..0000000000 --- a/tempest/api/orchestration/stacks/templates/nova_keypair.yaml +++ /dev/null @@ -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] } diff --git a/tempest/api/orchestration/stacks/templates/random_string.yaml b/tempest/api/orchestration/stacks/templates/random_string.yaml deleted file mode 100644 index dfd23424b6..0000000000 --- a/tempest/api/orchestration/stacks/templates/random_string.yaml +++ /dev/null @@ -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]} diff --git a/tempest/api/orchestration/stacks/templates/swift_basic.yaml b/tempest/api/orchestration/stacks/templates/swift_basic.yaml deleted file mode 100644 index 713f8bc122..0000000000 --- a/tempest/api/orchestration/stacks/templates/swift_basic.yaml +++ /dev/null @@ -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] } diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py deleted file mode 100644 index c8a9aa7343..0000000000 --- a/tempest/api/orchestration/stacks/test_environment.py +++ /dev/null @@ -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)) diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py deleted file mode 100644 index 9c9d4f98e9..0000000000 --- a/tempest/api/orchestration/stacks/test_limits.py +++ /dev/null @@ -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)) diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py deleted file mode 100644 index 36881bfbd6..0000000000 --- a/tempest/api/orchestration/stacks/test_neutron_resources.py +++ /dev/null @@ -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) diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py deleted file mode 100644 index 6b9c88be97..0000000000 --- a/tempest/api/orchestration/stacks/test_non_empty_stack.py +++ /dev/null @@ -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']) diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py deleted file mode 100644 index a51648fbb9..0000000000 --- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py +++ /dev/null @@ -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' diff --git a/tempest/api/orchestration/stacks/test_resource_types.py b/tempest/api/orchestration/stacks/test_resource_types.py deleted file mode 100644 index 6d0707e552..0000000000 --- a/tempest/api/orchestration/stacks/test_resource_types.py +++ /dev/null @@ -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') diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py deleted file mode 100644 index 81929995b7..0000000000 --- a/tempest/api/orchestration/stacks/test_soft_conf.py +++ /dev/null @@ -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) diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py deleted file mode 100644 index dc1bb4f817..0000000000 --- a/tempest/api/orchestration/stacks/test_stacks.py +++ /dev/null @@ -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') diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py deleted file mode 100644 index d63cde8e1b..0000000000 --- a/tempest/api/orchestration/stacks/test_swift_resources.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2013 eNovance SAS -# -# 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]) diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py deleted file mode 100644 index 4ff951d5b6..0000000000 --- a/tempest/api/orchestration/stacks/test_templates.py +++ /dev/null @@ -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" - } - } -} -""" diff --git a/tempest/api/orchestration/stacks/test_templates_negative.py b/tempest/api/orchestration/stacks/test_templates_negative.py deleted file mode 100644 index eb93d95a9d..0000000000 --- a/tempest/api/orchestration/stacks/test_templates_negative.py +++ /dev/null @@ -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' diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py deleted file mode 100644 index 7ddf7afd3d..0000000000 --- a/tempest/api/orchestration/stacks/test_volumes.py +++ /dev/null @@ -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