Browse Source

Remove tests for Interop Tests for add-on trademark program

Remove tests which been planned to added to add-on trademark
program. We now maintain these tests in heat tempest plugin.

Change-Id: I458d39f988019c4f1d62c7e39a325a2082a98561
changes/68/528568/10
ricolin 5 years ago committed by Zane Bitter
parent
commit
d2bf5ecf6a
  1. 0
      heat_integrationtests/api/__init__.py
  2. 55
      heat_integrationtests/api/gabbits/environments.yaml
  3. 90
      heat_integrationtests/api/gabbits/resources.yaml
  4. 24
      heat_integrationtests/api/gabbits/resourcetypes.yaml
  5. 162
      heat_integrationtests/api/gabbits/stacks.yaml
  6. 37
      heat_integrationtests/api/gabbits/templates.yaml
  7. 44
      heat_integrationtests/api/test_heat_api.py
  8. 83
      heat_integrationtests/functional/test_external_ref.py
  9. 281
      heat_integrationtests/functional/test_hooks.py
  10. 237
      heat_integrationtests/functional/test_preview.py
  11. 50
      heat_integrationtests/functional/test_resources_list.py
  12. 157
      heat_integrationtests/functional/test_software_config.py
  13. 109
      heat_integrationtests/functional/test_stack_events.py
  14. 155
      heat_integrationtests/functional/test_stack_outputs.py
  15. 77
      heat_integrationtests/functional/test_stack_tags.py
  16. 292
      heat_integrationtests/functional/test_template_validate.py
  17. 31
      heat_integrationtests/functional/test_template_versions.py
  18. 72
      heat_integrationtests/functional/test_templates.py
  19. 122
      heat_integrationtests/functional/test_unicode_template.py
  20. 2
      heat_integrationtests/post_test_hook.sh
  21. 110
      heat_integrationtests/scenario/templates/test_base_resources.yaml
  22. 73
      heat_integrationtests/scenario/test_base_resources.py
  23. 1
      test-requirements.txt

0
heat_integrationtests/api/__init__.py

55
heat_integrationtests/api/gabbits/environments.yaml

@ -1,55 +0,0 @@
defaults:
request_headers:
X-Auth-Token: $ENVIRON['OS_TOKEN']
tests:
- name: environment with parameter
POST: /stacks
request_headers:
content-type: application/json
data:
files: {}
disable_rollback: true
parameters: {}
stack_name: $ENVIRON['PREFIX']-envstack
environment:
parameters:
test_val: test
template:
heat_template_version: '2016-04-08'
parameters:
test_val:
type: string
resources:
test:
type: OS::Heat::TestResource
properties:
value: {get_param: test_val}
outputs:
output_value:
value: {get_attr: [test, output]}
status: 201
response_headers:
location: //stacks/$ENVIRON['PREFIX']-envstack/[a-f0-9-]+/
- name: poll for envstack CREATE_COMPLETE
GET: $LOCATION
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: CREATE_COMPLETE
- name: get stack output
GET: $LAST_URL/outputs/output_value
redirects: True
status: 200
response_json_paths:
$.output.output_value: test
- name: delete envstack
DELETE: /stacks/$ENVIRON['PREFIX']-envstack
redirects: True
status: 204

90
heat_integrationtests/api/gabbits/resources.yaml

@ -1,90 +0,0 @@
defaults:
request_headers:
X-Auth-Token: $ENVIRON['OS_TOKEN']
tests:
- name: create stack with resources
POST: /stacks
request_headers:
content-type: application/json
data:
files: {}
disable_rollback: true
parameters: {}
stack_name: $ENVIRON['PREFIX']-rsrcstack
template:
heat_template_version: '2016-04-08'
parameters:
test_val:
type: string
default: test
resources:
test:
type: OS::Heat::TestResource
properties:
value: {get_param: test_val}
status: 201
response_headers:
location: //stacks/$ENVIRON['PREFIX']-rsrcstack/[a-f0-9-]+/
- name: poll for rsrcstack CREATE_COMPLETE
GET: $LOCATION
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: CREATE_COMPLETE
- name: list resources
GET: $LAST_URL/resources
request_headers:
content-type: application/json
status: 200
response_json_paths:
$.resources[0].logical_resource_id: test
$.resources[0].resource_status: CREATE_COMPLETE
- name: list filtered resources
GET: $LAST_URL
request_headers:
content-type: application/json
query_parameters:
type: OS::Nova::Server
status: 200
response_json_paths:
$.resources: []
- name: show resource
GET: $LAST_URL/test
request_headers:
content-type: application/json
status: 200
response_json_paths:
$.resource.attributes.output: test
- name: mark resource unhealthy
PATCH: $LAST_URL
request_headers:
content-type: application/json
data:
mark_unhealthy: true
resource_status_reason: 'resource deleted'
status: 200
- name: show unhealthy resource
GET: $LAST_URL
status: 200
response_json_paths:
$.resource.resource_status: CHECK_FAILED
$.resource.resource_status_reason: 'resource deleted'
- name: signal resource
POST: $LAST_URL/signal
status: 400
- name: delete stack with resources
DELETE: /stacks/$ENVIRON['PREFIX']-rsrcstack
redirects: True
status: 204

24
heat_integrationtests/api/gabbits/resourcetypes.yaml

@ -1,24 +0,0 @@
defaults:
request_headers:
X-Auth-Token: $ENVIRON['OS_TOKEN']
tests:
- name: list resource types
GET: /resource_types
status: 200
- name: show resource type
GET: /resource_types/OS::Heat::TestResource
status: 200
response_json_paths:
$.support_status.status: SUPPORTED
$.properties.wait_secs.default: 0
- name: resource type template
GET: /resource_types/OS::Heat::TestResource/template
query_parameters:
template_type: hot
status: 200
response_json_paths:
$.resources.TestResource.type: OS::Heat::TestResource
$.heat_template_version: '2016-10-14'

162
heat_integrationtests/api/gabbits/stacks.yaml

@ -1,162 +0,0 @@
defaults:
request_headers:
X-Auth-Token: $ENVIRON['OS_TOKEN']
tests:
- name: stack list
GET: /stacks
status: 200
response_headers:
content-type: application/json
- name: create empty stack
POST: /stacks
request_headers:
content-type: application/json
data:
files: {}
disable_rollback: true
parameters: {}
stack_name: $ENVIRON['PREFIX']-empty
environment: {}
template:
heat_template_version: '2016-04-08'
status: 201
response_headers:
location: //stacks/$ENVIRON['PREFIX']-empty/[a-f0-9-]+/
- name: poll for empty CREATE_COMPLETE
GET: $LOCATION
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: CREATE_COMPLETE
- name: show empty stack
GET: $LAST_URL
redirects: True
status: 200
- name: delete empty stack
DELETE: $LAST_URL
redirects: True
status: 204
- name: create stack
POST: /stacks
request_headers:
content-type: application/json
data:
files: {}
disable_rollback: true
parameters: {'test_val': value}
stack_name: $ENVIRON['PREFIX']-stack
template:
heat_template_version: pike
parameters:
test_val:
type: string
resources:
test:
type: OS::Heat::TestResource
properties:
value: {get_param: test_val}
outputs:
output_value:
value: {get_attr: [test, output]}
status: 201
response_headers:
location: //stacks/$ENVIRON['PREFIX']-stack/[a-f0-9-]+/
- name: poll for stack CREATE_COMPLETE
GET: $LOCATION
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: CREATE_COMPLETE
- name: show stack
GET: $LAST_URL
redirects: True
status: 200
- name: update stack
PUT: $LAST_URL
request_headers:
content-type: application/json
data:
files: {}
disable_rollback: true
parameters: {'test_val': new_value}
stack_name: $ENVIRON['PREFIX']-stack
template:
heat_template_version: pike
parameters:
test_val:
type: string
resources:
test:
type: OS::Heat::TestResource
properties:
value: {get_param: test_val}
action_wait_secs:
update: 1
outputs:
output_value:
value: {get_attr: [test, output]}
status: 202
- name: poll for stack UPDATE_COMPLETE
GET: $LAST_URL
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: UPDATE_COMPLETE
- name: patch update stack
PATCH: $LAST_URL
request_headers:
content-type: application/json
data:
parameters: {'test_val': new_patched_value}
status: 202
- name: poll for stack patch UPDATE_COMPLETE
GET: $LAST_URL
redirects: True
poll:
count: 5
delay: 1.0
response_json_paths:
$.stack.stack_status: UPDATE_COMPLETE
$.stack.updated_time: /^(?!$HISTORY['poll for stack UPDATE_COMPLETE'].$RESPONSE['$.stack.updated_time'])/
- name: list stack outputs
GET: $LAST_URL/outputs
redirects: True
status: 200
response_json_paths:
$.outputs[0].output_key: output_value
- name: get stack output
GET: $LAST_URL/output_value
redirects: True
status: 200
response_json_paths:
$.output.output_value: new_patched_value
- name: delete stack
DELETE: /stacks/$ENVIRON['PREFIX']-stack
redirects: True
status: 204

37
heat_integrationtests/api/gabbits/templates.yaml

@ -1,37 +0,0 @@
defaults:
request_headers:
X-Auth-Token: $ENVIRON['OS_TOKEN']
tests:
- name: list template versions
GET: /template_versions
status: 200
response_json_paths:
$.template_versions[?(@.version='heat_template_version.2017-02-24')].type: hot
- name: list template functions
GET: /template_versions/heat_template_version.2016-10-14/functions
status: 200
response_json_paths:
$.template_functions[?(@.functions='get_file')].description:
A function for including a file inline.
- name: template validate
POST: /validate
request_headers:
content-type: application/json
data:
template:
heat_template_version: '2016-04-08'
parameters:
test_val:
type: string
resources:
test:
type: OS::Heat::TestResource
properties:
value: {get_param: test_val}
outputs:
output_value:
value: {get_attr: [test, output]}
status: 200

44
heat_integrationtests/api/test_heat_api.py

@ -1,44 +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.
"""A test module to exercise the Heat API with gabbi. """
import os
from gabbi import driver
from six.moves.urllib import parse as urlparse
from heat_integrationtests.common import clients
from heat_integrationtests.common import config
from heat_integrationtests.common import test
TESTS_DIR = 'gabbits'
def load_tests(loader, tests, pattern):
"""Provide a TestSuite to the discovery process."""
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
conf = config.init_conf().heat_plugin
if conf.auth_url is None:
# It's not configured, let's not load tests
return
manager = clients.ClientManager(conf)
endpoint = manager.identity_client.get_endpoint_url(
'orchestration', conf.region)
host = urlparse.urlparse(endpoint).hostname
os.environ['OS_TOKEN'] = manager.identity_client.auth_token
os.environ['PREFIX'] = test.rand_name('api')
return driver.build_tests(test_dir, loader, host=host,
url=endpoint, test_loader_name=__name__)

83
heat_integrationtests/functional/test_external_ref.py

@ -1,83 +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 heat_integrationtests.functional import functional_base
class ExternalReferencesTest(functional_base.FunctionalTestsBase):
TEMPLATE = '''
heat_template_version: 2016-10-14
resources:
test1:
type: OS::Heat::TestResource
'''
TEMPLATE_WITH_EX_REF = '''
heat_template_version: 2016-10-14
resources:
test1:
type: OS::Heat::TestResource
external_id: foobar
outputs:
str:
value: {get_resource: test1}
'''
def test_create_with_external_ref(self):
stack_name = self._stack_rand_name()
stack_identifier = self.stack_create(
stack_name=stack_name,
template=self.TEMPLATE_WITH_EX_REF,
files={},
disable_rollback=True,
parameters={},
environment={}
)
stack = self.client.stacks.get(stack_identifier)
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
expected_resources = {'test1': 'OS::Heat::TestResource'}
self.assertEqual(expected_resources,
self.list_resources(stack_identifier))
stack = self.client.stacks.get(stack_identifier)
self.assertEqual(
[{'description': 'No description given',
'output_key': 'str',
'output_value': 'foobar'}], stack.outputs)
def test_update_with_external_ref(self):
stack_name = self._stack_rand_name()
stack_identifier = self.stack_create(
stack_name=stack_name,
template=self.TEMPLATE,
files={},
disable_rollback=True,
parameters={},
environment={}
)
stack = self.client.stacks.get(stack_identifier)
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
expected_resources = {'test1': 'OS::Heat::TestResource'}
self.assertEqual(expected_resources,
self.list_resources(stack_identifier))
stack = self.client.stacks.get(stack_identifier)
self.assertEqual([], stack.outputs)
stack_name = stack_identifier.split('/')[0]
kwargs = {'stack_id': stack_identifier, 'stack_name': stack_name,
'template': self.TEMPLATE_WITH_EX_REF, 'files': {},
'disable_rollback': True, 'parameters': {}, 'environment': {}
}
self.client.stacks.update(**kwargs)
self._wait_for_stack_status(stack_identifier, 'UPDATE_FAILED')

281
heat_integrationtests/functional/test_hooks.py

@ -1,281 +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 yaml
from heat_integrationtests.functional import functional_base
class HooksTest(functional_base.FunctionalTestsBase):
def setUp(self):
super(HooksTest, self).setUp()
self.template = {'heat_template_version': '2014-10-16',
'resources': {
'foo_step1': {'type': 'OS::Heat::RandomString'},
'foo_step2': {'type': 'OS::Heat::RandomString',
'depends_on': 'foo_step1'},
'foo_step3': {'type': 'OS::Heat::RandomString',
'depends_on': 'foo_step2'}}}
def test_hook_pre_create(self):
env = {'resource_registry':
{'resources':
{'foo_step2':
{'hooks': 'pre-create'}}}}
# Note we don't wait for CREATE_COMPLETE, because we need to
# signal to clear the hook before create will complete
stack_identifier = self.stack_create(
template=self.template,
environment=env,
expected_status='CREATE_IN_PROGRESS')
self._wait_for_resource_status(
stack_identifier, 'foo_step1', 'CREATE_COMPLETE')
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'INIT_COMPLETE')
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='CREATE paused until Hook pre-create is cleared',
rsrc_name='foo_step2')
self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
self.client.resources.signal(stack_identifier, 'foo_step2',
data={'unset_hook': 'pre-create'})
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-create is cleared',
rsrc_name='foo_step2')
self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
def test_hook_pre_update_nochange(self):
env = {'resource_registry':
{'resources':
{'foo_step2':
{'hooks': 'pre-update'}}}}
stack_identifier = self.stack_create(
template=self.template,
environment=env)
res_before = self.client.resources.get(stack_identifier, 'foo_step2')
# Note we don't wait for UPDATE_COMPLETE, because we need to
# signal to clear the hook before update will complete
self.update_stack(
stack_identifier,
template=self.template,
environment=env,
expected_status='UPDATE_IN_PROGRESS')
# Note when a hook is specified, the resource status doesn't change
# when we hit the hook, so we look for the event, then assert the
# state is unchanged.
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='UPDATE paused until Hook pre-update is cleared',
rsrc_name='foo_step2')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self.client.resources.signal(stack_identifier, 'foo_step2',
data={'unset_hook': 'pre-update'})
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-update is cleared',
rsrc_name='foo_step2')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
res_after = self.client.resources.get(stack_identifier, 'foo_step2')
self.assertEqual(res_before.physical_resource_id,
res_after.physical_resource_id)
def test_hook_pre_update_replace(self):
env = {'resource_registry':
{'resources':
{'foo_step2':
{'hooks': 'pre-update'}}}}
stack_identifier = self.stack_create(
template=self.template,
environment=env)
res_before = self.client.resources.get(stack_identifier, 'foo_step2')
# Note we don't wait for UPDATE_COMPLETE, because we need to
# signal to clear the hook before update will complete
self.template['resources']['foo_step2']['properties'] = {'length': 10}
self.update_stack(
stack_identifier,
template=self.template,
environment=env,
expected_status='UPDATE_IN_PROGRESS')
# Note when a hook is specified, the resource status doesn't change
# when we hit the hook, so we look for the event, then assert the
# state is unchanged.
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='UPDATE paused until Hook pre-update is cleared',
rsrc_name='foo_step2')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self.client.resources.signal(stack_identifier, 'foo_step2',
data={'unset_hook': 'pre-update'})
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-update is cleared',
rsrc_name='foo_step2')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
res_after = self.client.resources.get(stack_identifier, 'foo_step2')
self.assertNotEqual(res_before.physical_resource_id,
res_after.physical_resource_id)
def test_hook_pre_update_in_place(self):
env = {'resource_registry':
{'resources':
{'rg':
{'hooks': 'pre-update'}}}}
template = {'heat_template_version': '2014-10-16',
'resources': {
'rg': {
'type': 'OS::Heat::ResourceGroup',
'properties': {
'count': 1,
'resource_def': {
'type': 'OS::Heat::RandomString'}}}}}
# Note we don't wait for CREATE_COMPLETE, because we need to
# signal to clear the hook before create will complete
stack_identifier = self.stack_create(
template=template,
environment=env)
res_before = self.client.resources.get(stack_identifier, 'rg')
template['resources']['rg']['properties']['count'] = 2
self.update_stack(
stack_identifier,
template=template,
environment=env,
expected_status='UPDATE_IN_PROGRESS')
# Note when a hook is specified, the resource status doesn't change
# when we hit the hook, so we look for the event, then assert the
# state is unchanged.
self._wait_for_resource_status(
stack_identifier, 'rg', 'CREATE_COMPLETE')
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='UPDATE paused until Hook pre-update is cleared',
rsrc_name='rg')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self.client.resources.signal(stack_identifier, 'rg',
data={'unset_hook': 'pre-update'})
ev = self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-update is cleared',
rsrc_name='rg')
self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
res_after = self.client.resources.get(stack_identifier, 'rg')
self.assertEqual(res_before.physical_resource_id,
res_after.physical_resource_id)
def test_hook_pre_create_nested(self):
files = {'nested.yaml': yaml.safe_dump(self.template)}
env = {'resource_registry':
{'resources':
{'nested':
{'foo_step2':
{'hooks': 'pre-create'}}}}}
template = {'heat_template_version': '2014-10-16',
'resources': {
'nested': {'type': 'nested.yaml'}}}
# Note we don't wait for CREATE_COMPLETE, because we need to
# signal to clear the hook before create will complete
stack_identifier = self.stack_create(
template=template,
environment=env,
files=files,
expected_status='CREATE_IN_PROGRESS')
self._wait_for_resource_status(stack_identifier, 'nested',
'CREATE_IN_PROGRESS')
nested_identifier = self.assert_resource_is_a_stack(
stack_identifier, 'nested', wait=True)
self._wait_for_resource_status(
nested_identifier, 'foo_step1', 'CREATE_COMPLETE')
self._wait_for_resource_status(
nested_identifier, 'foo_step2', 'INIT_COMPLETE')
ev = self.wait_for_event_with_reason(
nested_identifier,
reason='CREATE paused until Hook pre-create is cleared',
rsrc_name='foo_step2')
self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
self.client.resources.signal(nested_identifier, 'foo_step2',
data={'unset_hook': 'pre-create'})
ev = self.wait_for_event_with_reason(
nested_identifier,
reason='Hook pre-create is cleared',
rsrc_name='foo_step2')
self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
self._wait_for_resource_status(
nested_identifier, 'foo_step2', 'CREATE_COMPLETE')
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
def test_hook_pre_create_wildcard(self):
env = {'resource_registry':
{'resources':
{'foo_*':
{'hooks': 'pre-create'}}}}
# Note we don't wait for CREATE_COMPLETE, because we need to
# signal to clear the hook before create will complete
stack_identifier = self.stack_create(
template=self.template,
environment=env,
expected_status='CREATE_IN_PROGRESS')
self._wait_for_resource_status(
stack_identifier, 'foo_step1', 'INIT_COMPLETE')
self.wait_for_event_with_reason(
stack_identifier,
reason='CREATE paused until Hook pre-create is cleared',
rsrc_name='foo_step1')
self.client.resources.signal(stack_identifier, 'foo_step1',
data={'unset_hook': 'pre-create'})
self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-create is cleared',
rsrc_name='foo_step1')
self._wait_for_resource_status(
stack_identifier, 'foo_step2', 'INIT_COMPLETE')
self.wait_for_event_with_reason(
stack_identifier,
reason='CREATE paused until Hook pre-create is cleared',
rsrc_name='foo_step2')
self.client.resources.signal(stack_identifier, 'foo_step2',
data={'unset_hook': 'pre-create'})
self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-create is cleared',
rsrc_name='foo_step2')
self._wait_for_resource_status(
stack_identifier, 'foo_step3', 'INIT_COMPLETE')
self.wait_for_event_with_reason(
stack_identifier,
reason='CREATE paused until Hook pre-create is cleared',
rsrc_name='foo_step3')
self.client.resources.signal(stack_identifier, 'foo_step3',
data={'unset_hook': 'pre-create'})
self.wait_for_event_with_reason(
stack_identifier,
reason='Hook pre-create is cleared',
rsrc_name='foo_step3')
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')

237
heat_integrationtests/functional/test_preview.py

@ -1,237 +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 heat_integrationtests.functional import functional_base
from heatclient import exc
import six
class StackPreviewTest(functional_base.FunctionalTestsBase):
template = '''
heat_template_version: 2015-04-30
parameters:
incomming:
type: string
resources:
one:
type: OS::Heat::TestResource
properties:
value: fred
two:
type: OS::Heat::TestResource
properties:
value: {get_param: incomming}
depends_on: one
outputs:
main_out:
value: {get_attr: [two, output]}
'''
env = '''
parameters:
incomming: abc
'''
def setUp(self):
super(StackPreviewTest, self).setUp()
self.client = self.orchestration_client
self.project_id = self.identity_client.project_id
def _assert_resource(self, res, stack_name):
self.assertEqual(stack_name, res['stack_name'])
self.assertEqual('INIT', res['resource_action'])
self.assertEqual('COMPLETE', res['resource_status'])
for field in ('resource_status_reason', 'physical_resource_id',
'description'):
self.assertIn(field, res)
self.assertEqual('', res[field])
# 'creation_time' and 'updated_time' are None when preview
for field in ('creation_time', 'updated_time'):
self.assertIn(field, res)
self.assertIsNone(res[field])
self.assertIn('output', res['attributes'])
# resource_identity
self.assertEqual(stack_name,
res['resource_identity']['stack_name'])
self.assertEqual('None', res['resource_identity']['stack_id'])
self.assertEqual(self.project_id,
res['resource_identity']['tenant'])
self.assertEqual('/resources/%s' % res['resource_name'],
res['resource_identity']['path'])
# stack_identity
self.assertEqual(stack_name,
res['stack_identity']['stack_name'])
self.assertEqual('None', res['stack_identity']['stack_id'])
self.assertEqual(self.project_id,
res['stack_identity']['tenant'])
self.assertEqual('', res['stack_identity']['path'])
def _assert_results(self, result, stack_name):
# global stuff.
self.assertEqual(stack_name, result['stack_name'])
self.assertTrue(result['disable_rollback'])
self.assertEqual('None', result['id'])
self.assertIsNone(result['parent'])
self.assertEqual('No description', result['template_description'])
# parameters
self.assertEqual('None', result['parameters']['OS::stack_id'])
self.assertEqual(stack_name, result['parameters']['OS::stack_name'])
self.assertEqual('abc', result['parameters']['incomming'])
def test_basic_pass(self):
stack_name = self._stack_rand_name()
result = self.client.stacks.preview(
template=self.template,
stack_name=stack_name,
disable_rollback=True,
environment=self.env).to_dict()
self._assert_results(result, stack_name)
for res in result['resources']:
self._assert_resource(res, stack_name)
self.assertEqual('OS::Heat::TestResource',
res['resource_type'])
# common properties
self.assertFalse(res['properties']['fail'])
self.assertEqual(0, res['properties']['wait_secs'])
self.assertFalse(res['properties']['update_replace'])
if res['resource_name'] == 'one':
self.assertEqual('fred', res['properties']['value'])
self.assertEqual(['two'], res['required_by'])
if res['resource_name'] == 'two':
self.assertEqual('abc', res['properties']['value'])
self.assertEqual([], res['required_by'])
def test_basic_fail(self):
stack_name = self._stack_rand_name()
# break the template so it fails validation.
wont_work = self.template.replace('get_param: incomming',
'get_param: missing')
excp = self.assertRaises(exc.HTTPBadRequest,
self.client.stacks.preview,
template=wont_work,
stack_name=stack_name,
disable_rollback=True,
environment=self.env)
self.assertIn('Property error: : resources.two.properties.value: '
': The Parameter (missing) was not provided.',
six.text_type(excp))
def test_nested_pass(self):
"""Nested stacks need to recurse down the stacks."""
main_template = '''
heat_template_version: 2015-04-30
parameters:
incomming:
type: string
resources:
main:
type: nested.yaml
properties:
value: {get_param: incomming}
outputs:
main_out:
value: {get_attr: [main, output]}
'''
nested_template = '''
heat_template_version: 2015-04-30
parameters:
value:
type: string
resources:
nested:
type: OS::Heat::TestResource
properties:
value: {get_param: value}
outputs:
output:
value: {get_attr: [nested, output]}
'''
stack_name = self._stack_rand_name()
result = self.client.stacks.preview(
disable_rollback=True,
stack_name=stack_name,
template=main_template,
files={'nested.yaml': nested_template},
environment=self.env).to_dict()
self._assert_results(result, stack_name)
# nested resources return a list of their resources.
res = result['resources'][0][0]
nested_stack_name = '%s-%s' % (stack_name,
res['parent_resource'])
self._assert_resource(res, nested_stack_name)
self.assertEqual('OS::Heat::TestResource',
res['resource_type'])
self.assertFalse(res['properties']['fail'])
self.assertEqual(0, res['properties']['wait_secs'])
self.assertFalse(res['properties']['update_replace'])
self.assertEqual('abc', res['properties']['value'])
self.assertEqual([], res['required_by'])
def test_res_group_with_nested_template(self):
main_template = '''
heat_template_version: 2015-04-30
resources:
fixed_network:
type: "OS::Neutron::Net"
rg:
type: "OS::Heat::ResourceGroup"
properties:
count: 1
resource_def:
type: nested.yaml
properties:
fixed_network_id: {get_resource: fixed_network}
'''
nested_template = '''
heat_template_version: 2015-04-30
parameters:
fixed_network_id:
type: string
resources:
port:
type: "OS::Neutron::Port"
properties:
network_id:
get_param: fixed_network_id
'''
stack_name = self._stack_rand_name()
result = self.client.stacks.preview(
disable_rollback=True,
stack_name=stack_name,
template=main_template,
files={'nested.yaml': nested_template}).to_dict()
resource_names = []
def get_resource_names(resources):
for item in resources:
if isinstance(item, dict):
resource_names.append(item['resource_name'])
else:
get_resource_names(item)
get_resource_names(result['resources'])
# ensure that fixed network and port here
self.assertIn('fixed_network', resource_names)
self.assertIn('port', resource_names)

50
heat_integrationtests/functional/test_resources_list.py

@ -1,50 +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 heat_integrationtests.functional import functional_base
test_template_depend = {
'heat_template_version': '2013-05-23',
'resources': {
'test1': {
'type': 'OS::Heat::TestResource',
'properties': {
'value': 'Test1',
}
},
'test2': {
'type': 'OS::Heat::TestResource',
'depends_on': ['test1'],
'properties': {
'value': 'Test2',
}
}
}
}
class ResourcesList(functional_base.FunctionalTestsBase):
def test_filtering_with_depend(self):
stack_identifier = self.stack_create(template=test_template_depend)
[test2] = self.client.resources.list(stack_identifier,
filters={'name': 'test2'})
self.assertEqual('CREATE_COMPLETE', test2.resource_status)
def test_required_by(self):
stack_identifier = self.stack_create(template=test_template_depend)
[test1] = self.client.resources.list(stack_identifier,
filters={'name': 'test1'})
self.assertEqual(['test2'], test1.required_by)

157
heat_integrationtests/functional/test_software_config.py

@ -12,174 +12,17 @@
import json
import os
import requests
import subprocess
import sys
import tempfile
import time
import yaml
from oslo_utils import timeutils
from heat_integrationtests.common import exceptions
from heat_integrationtests.common import test
from heat_integrationtests.functional import functional_base
class ParallelDeploymentsTest(functional_base.FunctionalTestsBase):
server_template = '''
heat_template_version: "2013-05-23"
parameters:
flavor:
type: string
image:
type: string
network:
type: string
resources:
server:
type: OS::Nova::Server
properties:
image: {get_param: image}
flavor: {get_param: flavor}
user_data_format: SOFTWARE_CONFIG
networks: [{network: {get_param: network}}]
outputs:
server:
value: {get_resource: server}
'''
config_template = '''
heat_template_version: "2013-05-23"
parameters:
server:
type: string
resources:
config:
type: OS::Heat::SoftwareConfig
properties:
'''
deployment_snippet = '''
type: OS::Heat::SoftwareDeployments
properties:
config: {get_resource: config}
servers: {'0': {get_param: server}}
'''
enable_cleanup = True
def test_deployments_metadata(self):
parms = {'flavor': self.conf.minimal_instance_type,
'network': self.conf.fixed_network_name,
'image': self.conf.minimal_image_ref}
stack_identifier = self.stack_create(
parameters=parms,
template=self.server_template,
enable_cleanup=self.enable_cleanup)
server_stack = self.client.stacks.get(stack_identifier)
server = server_stack.outputs[0]['output_value']
config_stacks = []
# add up to 3 stacks each with up to 3 deployments
deploy_count = 0
deploy_count = self.deploy_many_configs(
stack_identifier,
server,
config_stacks,
2,
5,
deploy_count)
self.deploy_many_configs(
stack_identifier,
server,
config_stacks,
3,
3,
deploy_count)
self.signal_deployments(stack_identifier)
for config_stack in config_stacks:
self._wait_for_stack_status(config_stack, 'CREATE_COMPLETE')
def test_deployments_timeout_failed(self):
parms = {'flavor': self.conf.minimal_instance_type,
'network': self.conf.fixed_network_name,
'image': self.conf.minimal_image_ref}
stack_identifier = self.stack_create(
parameters=parms,
template=self.server_template,
enable_cleanup=self.enable_cleanup)
server_stack = self.client.stacks.get(stack_identifier)
server = server_stack.outputs[0]['output_value']
config_stack = self.deploy_config(server, 3, 1)
self._wait_for_stack_status(config_stack, 'CREATE_FAILED')
kwargs = {'server_id': server}
def check_deployment_status():
sd_list = self.client.software_deployments.list(**kwargs)
for sd in sd_list:
if sd.status != 'FAILED':
return False
return True
self.assertTrue(test.call_until_true(
20, 0, check_deployment_status))
def deploy_many_configs(self, stack, server, config_stacks,
stack_count, deploys_per_stack,
deploy_count_start):
for a in range(stack_count):
config_stacks.append(
self.deploy_config(server, deploys_per_stack))
new_count = deploy_count_start + stack_count * deploys_per_stack
self.wait_for_deploy_metadata_set(stack, new_count)
return new_count
def deploy_config(self, server, deploy_count, timeout=None):
parms = {'server': server}
template = yaml.safe_load(self.config_template)
resources = template['resources']
resources['config']['properties'] = {'config': 'x' * 10000}
for a in range(deploy_count):
resources['dep_%s' % a] = yaml.safe_load(self.deployment_snippet)
return self.stack_create(
parameters=parms,
template=template,
enable_cleanup=self.enable_cleanup,
expected_status=None,
timeout=timeout)
def wait_for_deploy_metadata_set(self, stack, deploy_count):
build_timeout = self.conf.build_timeout
build_interval = self.conf.build_interval
start = timeutils.utcnow()
while timeutils.delta_seconds(start,
timeutils.utcnow()) < build_timeout:
server_metadata = self.client.resources.metadata(
stack, 'server')
if len(server_metadata['deployments']) == deploy_count:
return
time.sleep(build_interval)
message = ('Deployment resources failed to be created within '
'the required time (%s s).' %
(build_timeout))
raise exceptions.TimeoutException(message)
def signal_deployments(self, stack_identifier):
server_metadata = self.client.resources.metadata(
stack_identifier, 'server')
for dep in server_metadata['deployments']:
iv = dict((i['name'], i['value']) for i in dep['inputs'])
sigurl = iv.get('deploy_signal_id')
requests.post(sigurl, data='{}',
headers={'content-type': 'application/json'},
verify=self.verify_cert)
class ZaqarSignalTransportTest(functional_base.FunctionalTestsBase):
server_template = '''
heat_template_version: "2013-05-23"

109
heat_integrationtests/functional/test_stack_events.py

@ -1,109 +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 heat_integrationtests.functional import functional_base
class StackEventsTest(functional_base.FunctionalTestsBase):
template = '''
heat_template_version: 2014-10-16
parameters:
resources:
test_resource:
type: OS::Heat::TestResource
properties:
value: 'test1'
fail: False
update_replace: False
wait_secs: 0
outputs:
resource_id:
description: 'ID of resource'
value: { get_resource: test_resource }
'''
def _verify_event_fields(self, event, event_characteristics):
self.assertIsNotNone(event_characteristics)
self.assertIsNotNone(event.event_time)
self.assertIsNotNone(event.links)
self.assertIsNotNone(event.logical_resource_id)
self.assertIsNotNone(event.resource_status)
self.assertIn(event.resource_status, event_characteristics[1])
self.assertIsNotNone(event.resource_status_reason)
self.assertIsNotNone(event.id)
def test_event(self):
parameters = {}
test_stack_name = self._stack_rand_name()
stack_identifier = self.stack_create(
stack_name=test_stack_name,
template=self.template,
parameters=parameters
)
expected_status = ['CREATE_IN_PROGRESS', 'CREATE_COMPLETE']
event_characteristics = {
test_stack_name: ('OS::Heat::Stack', expected_status),
'test_resource': ('OS::Heat::TestResource', expected_status)}
# List stack events
# API: GET /v1/{tenant_id}/stacks/{stack_name}/{stack_id}/events
stack_events = self.client.events.list(stack_identifier)
for stack_event in stack_events:
# Key on an expected/valid resource name
self._verify_event_fields(
stack_event,
event_characteristics[stack_event.resource_name])
# Test the event filtering API based on this resource_name
# /v1/{tenant_id}/stacks/{stack_name}/{stack_id}/resources/{resource_name}/events
resource_events = self.client.events.list(
stack_identifier,
stack_event.resource_name)
# Resource events are a subset of the original stack event list
self.assertLess(len(resource_events), len(stack_events))
# Get the event details for each resource event
for resource_event in resource_events:
# A resource_event should be in the original stack event list
self.assertIn(resource_event, stack_events)
# Given a filtered list, the resource names should be identical
self.assertEqual(
resource_event.resource_name,
stack_event.resource_name)
# Verify all fields, keying off the resource_name
self._verify_event_fields(
resource_event,
event_characteristics[resource_event.resource_name])
# Exercise the event details API
# /v1/{tenant_id}/stacks/{stack_name}/{stack_id}/resources/{resource_name}/events/{event_id}
event_details = self.client.events.get(
stack_identifier,
resource_event.resource_name,
resource_event.id)
self._verify_event_fields(
event_details,
event_characteristics[event_details.resource_name])
# The names should be identical to the non-detailed event
self.assertEqual(
resource_event.resource_name,
event_details.resource_name)
# Verify the extra field in the detail results
self.assertIsNotNone(event_details.resource_type)
self.assertEqual(
event_characteristics[event_details.resource_name][0],
event_details.resource_type)

155
heat_integrationtests/functional/test_stack_outputs.py

@ -1,155 +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
#