Adds tests for Heat
Tests and client methods for: - template-show - template-validate - template-url-validate - stack-list - stack-show - resource-list - resource-show - resource-metadata - event-list - event-show Testing Neutron resources: - network - subnet - router_interface Testing server property: - subnet_id Change-Id: I47bb0dd653da51c9ff1d2ffe0b02c102cc0098d5
This commit is contained in:
parent
0042d2de86
commit
ab33b7e502
|
@ -89,8 +89,8 @@ class BaseOrchestrationTest(tempest.test.BaseTestCase):
|
|||
pass
|
||||
|
||||
@classmethod
|
||||
def _create_keypair(cls, namestart='keypair-heat-'):
|
||||
kp_name = rand_name(namestart)
|
||||
def _create_keypair(cls, name_start='keypair-heat-'):
|
||||
kp_name = rand_name(name_start)
|
||||
resp, body = cls.keypairs_client.create_keypair(kp_name)
|
||||
cls.keypairs.append(kp_name)
|
||||
return body
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from tempest.api.orchestration import base
|
||||
from tempest import clients
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest.test import attr
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NeutronResourcesTestJSON(base.BaseOrchestrationTest):
|
||||
_interface = 'json'
|
||||
|
||||
template = """
|
||||
HeatTemplateFormatVersion: '2012-12-12'
|
||||
Description: |
|
||||
Template which creates single EC2 instance
|
||||
Parameters:
|
||||
KeyName:
|
||||
Type: String
|
||||
InstanceType:
|
||||
Type: String
|
||||
ImageId:
|
||||
Type: String
|
||||
ExternalRouterId:
|
||||
Type: String
|
||||
Resources:
|
||||
Network:
|
||||
Type: OS::Quantum::Net
|
||||
Properties: {name: NewNetwork}
|
||||
Subnet:
|
||||
Type: OS::Quantum::Subnet
|
||||
Properties:
|
||||
network_id: {Ref: Network}
|
||||
name: NewSubnet
|
||||
ip_version: 4
|
||||
cidr: 10.0.3.0/24
|
||||
dns_nameservers: ["8.8.8.8"]
|
||||
allocation_pools:
|
||||
- {end: 10.0.3.150, start: 10.0.3.20}
|
||||
RouterInterface:
|
||||
Type: OS::Quantum::RouterInterface
|
||||
Properties:
|
||||
router_id: {Ref: ExternalRouterId}
|
||||
subnet_id: {Ref: Subnet}
|
||||
Server:
|
||||
Type: AWS::EC2::Instance
|
||||
Metadata:
|
||||
Name: SmokeServer
|
||||
Properties:
|
||||
ImageId: {Ref: ImageId}
|
||||
InstanceType: {Ref: InstanceType}
|
||||
KeyName: {Ref: KeyName}
|
||||
SubnetId: {Ref: Subnet}
|
||||
UserData:
|
||||
Fn::Base64:
|
||||
Fn::Join:
|
||||
- ''
|
||||
- - '#!/bin/bash -v
|
||||
|
||||
'
|
||||
- /opt/aws/bin/cfn-signal -e 0 -r "SmokeServer created" '
|
||||
- {Ref: WaitHandle}
|
||||
- '''
|
||||
|
||||
'
|
||||
WaitHandle:
|
||||
Type: AWS::CloudFormation::WaitConditionHandle
|
||||
WaitCondition:
|
||||
Type: AWS::CloudFormation::WaitCondition
|
||||
DependsOn: Server
|
||||
Properties:
|
||||
Handle: {Ref: WaitHandle}
|
||||
Timeout: '600'
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(NeutronResourcesTestJSON, cls).setUpClass()
|
||||
if not cls.orchestration_cfg.image_ref:
|
||||
raise cls.skipException("No image available to test")
|
||||
cls.client = cls.orchestration_client
|
||||
os = clients.Manager()
|
||||
cls.network_cfg = os.config.network
|
||||
if not cls.config.service_available.neutron:
|
||||
raise cls.skipException("Neutron support is required")
|
||||
cls.network_client = os.network_client
|
||||
cls.stack_name = rand_name('heat')
|
||||
cls.keypair_name = (cls.orchestration_cfg.keypair_name or
|
||||
cls._create_keypair()['name'])
|
||||
cls.external_router_id = cls._get_external_router_id()
|
||||
|
||||
# create the stack
|
||||
cls.stack_identifier = cls.create_stack(
|
||||
cls.stack_name,
|
||||
cls.template,
|
||||
parameters={
|
||||
'KeyName': cls.keypair_name,
|
||||
'InstanceType': cls.orchestration_cfg.instance_type,
|
||||
'ImageId': cls.orchestration_cfg.image_ref,
|
||||
'ExternalRouterId': cls.external_router_id
|
||||
})
|
||||
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)
|
||||
cls.test_resources = {}
|
||||
for resource in resources:
|
||||
cls.test_resources[resource['logical_resource_id']] = resource
|
||||
|
||||
@classmethod
|
||||
def _get_external_router_id(cls):
|
||||
resp, body = cls.network_client.list_ports()
|
||||
ports = body['ports']
|
||||
router_ports = filter(lambda port: port['device_owner'] ==
|
||||
'network:router_interface', ports)
|
||||
return router_ports[0]['device_id']
|
||||
|
||||
@attr(type='slow')
|
||||
def test_created_resources(self):
|
||||
"""Verifies created neutron resources."""
|
||||
resources = [('Network', 'OS::Quantum::Net'),
|
||||
('Subnet', 'OS::Quantum::Subnet'),
|
||||
('RouterInterface', 'OS::Quantum::RouterInterface'),
|
||||
('Server', 'AWS::EC2::Instance')]
|
||||
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'])
|
||||
|
||||
@attr(type='slow')
|
||||
def test_created_network(self):
|
||||
"""Verifies created netowrk."""
|
||||
network_id = self.test_resources.get('Network')['physical_resource_id']
|
||||
resp, body = self.network_client.show_network(network_id)
|
||||
self.assertEqual('200', resp['status'])
|
||||
network = body['network']
|
||||
self.assertIsInstance(network, dict)
|
||||
self.assertEqual(network_id, network['id'])
|
||||
self.assertEqual('NewNetwork', network['name'])
|
||||
|
||||
@attr(type='slow')
|
||||
def test_created_subnet(self):
|
||||
"""Verifies created subnet."""
|
||||
subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
|
||||
resp, body = self.network_client.show_subnet(subnet_id)
|
||||
self.assertEqual('200', resp['status'])
|
||||
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('NewSubnet', subnet['name'])
|
||||
self.assertEqual('8.8.8.8', subnet['dns_nameservers'][0])
|
||||
self.assertEqual('10.0.3.20', subnet['allocation_pools'][0]['start'])
|
||||
self.assertEqual('10.0.3.150', subnet['allocation_pools'][0]['end'])
|
||||
self.assertEqual(4, subnet['ip_version'])
|
||||
self.assertEqual('10.0.3.0/24', subnet['cidr'])
|
||||
|
||||
@attr(type='slow')
|
||||
def test_created_router_interface(self):
|
||||
"""Verifies created router interface."""
|
||||
network_id = self.test_resources.get('Network')['physical_resource_id']
|
||||
subnet_id = self.test_resources.get('Subnet')['physical_resource_id']
|
||||
resp, body = self.network_client.list_ports()
|
||||
self.assertEqual('200', resp['status'])
|
||||
ports = body['ports']
|
||||
router_ports = filter(lambda port: port['device_id'] ==
|
||||
self.external_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('10.0.3.1', router_interface_ip)
|
||||
|
||||
@attr(type='slow')
|
||||
def test_created_server(self):
|
||||
"""Verifies created sever."""
|
||||
server_id = self.test_resources.get('Server')['physical_resource_id']
|
||||
resp, server = self.servers_client.get_server(server_id)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertEqual(self.keypair_name, server['key_name'])
|
||||
self.assertEqual('ACTIVE', server['status'])
|
||||
network = server['addresses']['NewNetwork'][0]
|
||||
self.assertEqual(4, network['version'])
|
||||
ip_addr_prefix = network['addr'][:7]
|
||||
ip_addr_suffix = int(network['addr'].split('.')[3])
|
||||
self.assertEqual('10.0.3.', ip_addr_prefix)
|
||||
self.assertTrue(ip_addr_suffix >= 20)
|
||||
self.assertTrue(ip_addr_suffix <= 150)
|
|
@ -0,0 +1,169 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from tempest.api.orchestration import base
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest.test import attr
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StacksTestJSON(base.BaseOrchestrationTest):
|
||||
_interface = 'json'
|
||||
|
||||
template = """
|
||||
HeatTemplateFormatVersion: '2012-12-12'
|
||||
Description: |
|
||||
Template which creates single EC2 instance
|
||||
Parameters:
|
||||
KeyName:
|
||||
Type: String
|
||||
InstanceType:
|
||||
Type: String
|
||||
ImageId:
|
||||
Type: String
|
||||
Resources:
|
||||
SmokeServer:
|
||||
Type: AWS::EC2::Instance
|
||||
Metadata:
|
||||
Name: SmokeServer
|
||||
Properties:
|
||||
ImageId: {Ref: ImageId}
|
||||
InstanceType: {Ref: InstanceType}
|
||||
KeyName: {Ref: KeyName}
|
||||
UserData:
|
||||
Fn::Base64:
|
||||
Fn::Join:
|
||||
- ''
|
||||
- - '#!/bin/bash -v
|
||||
|
||||
'
|
||||
- /opt/aws/bin/cfn-signal -e 0 -r "SmokeServer created" '
|
||||
- {Ref: WaitHandle}
|
||||
- '''
|
||||
|
||||
'
|
||||
WaitHandle:
|
||||
Type: AWS::CloudFormation::WaitConditionHandle
|
||||
WaitCondition:
|
||||
Type: AWS::CloudFormation::WaitCondition
|
||||
DependsOn: SmokeServer
|
||||
Properties:
|
||||
Handle: {Ref: WaitHandle}
|
||||
Timeout: '600'
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(StacksTestJSON, cls).setUpClass()
|
||||
if not cls.orchestration_cfg.image_ref:
|
||||
raise cls.skipException("No image available to test")
|
||||
cls.client = cls.orchestration_client
|
||||
cls.stack_name = rand_name('heat')
|
||||
keypair_name = (cls.orchestration_cfg.keypair_name or
|
||||
cls._create_keypair()['name'])
|
||||
|
||||
# create the stack
|
||||
cls.stack_identifier = cls.create_stack(
|
||||
cls.stack_name,
|
||||
cls.template,
|
||||
parameters={
|
||||
'KeyName': keypair_name,
|
||||
'InstanceType': cls.orchestration_cfg.instance_type,
|
||||
'ImageId': cls.orchestration_cfg.image_ref
|
||||
})
|
||||
cls.stack_id = cls.stack_identifier.split('/')[1]
|
||||
cls.resource_name = 'SmokeServer'
|
||||
cls.resource_type = 'AWS::EC2::Instance'
|
||||
cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
|
||||
|
||||
@attr(type='slow')
|
||||
def test_stack_list(self):
|
||||
"""Created stack should be on the list of existing stacks."""
|
||||
resp, stacks = self.client.list_stacks()
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(stacks, list)
|
||||
stacks_names = map(lambda stack: stack['stack_name'], stacks)
|
||||
self.assertIn(self.stack_name, stacks_names)
|
||||
|
||||
@attr(type='slow')
|
||||
def test_stack_show(self):
|
||||
"""Getting details about created stack should be possible."""
|
||||
resp, stack = self.client.get_stack(self.stack_name)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(stack, dict)
|
||||
self.assertEqual(self.stack_name, stack['stack_name'])
|
||||
self.assertEqual(self.stack_id, stack['id'])
|
||||
|
||||
@attr(type='slow')
|
||||
def test_list_resources(self):
|
||||
"""Getting list of created resources for the stack should be possible.
|
||||
"""
|
||||
resp, resources = self.client.list_resources(self.stack_identifier)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(resources, list)
|
||||
resources_names = map(lambda resource: resource['logical_resource_id'],
|
||||
resources)
|
||||
self.assertIn(self.resource_name, resources_names)
|
||||
resources_types = map(lambda resource: resource['resource_type'],
|
||||
resources)
|
||||
self.assertIn(self.resource_type, resources_types)
|
||||
|
||||
@attr(type='slow')
|
||||
def test_show_resource(self):
|
||||
"""Getting details about created resource should be possible."""
|
||||
resp, resource = self.client.get_resource(self.stack_identifier,
|
||||
self.resource_name)
|
||||
self.assertIsInstance(resource, dict)
|
||||
self.assertEqual(self.resource_name, resource['logical_resource_id'])
|
||||
self.assertEqual(self.resource_type, resource['resource_type'])
|
||||
|
||||
@attr(type='slow')
|
||||
def test_resource_metadata(self):
|
||||
"""Getting metadata for created resource should be possible."""
|
||||
resp, metadata = self.client.show_resource_metadata(
|
||||
self.stack_identifier,
|
||||
self.resource_name)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(metadata, dict)
|
||||
self.assertEqual(self.resource_name, metadata.get('Name', None))
|
||||
|
||||
@attr(type='slow')
|
||||
def test_list_events(self):
|
||||
"""Getting list of created events for the stack should be possible."""
|
||||
resp, events = self.client.list_events(self.stack_identifier)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(events, list)
|
||||
resource_statuses = map(lambda event: event['resource_status'], events)
|
||||
self.assertIn('CREATE_IN_PROGRESS', resource_statuses)
|
||||
self.assertIn('CREATE_COMPLETE', resource_statuses)
|
||||
|
||||
@attr(type='slow')
|
||||
def test_show_event(self):
|
||||
"""Getting details about existing event should be possible."""
|
||||
resp, events = self.client.list_resource_events(self.stack_identifier,
|
||||
self.resource_name)
|
||||
self.assertNotEqual([], events)
|
||||
events.sort(key=lambda event: event['event_time'])
|
||||
event_id = events[0]['id']
|
||||
resp, event = self.client.show_event(self.stack_identifier,
|
||||
self.resource_name, event_id)
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertEqual('CREATE_IN_PROGRESS', event['resource_status'])
|
||||
self.assertEqual('state changed', event['resource_status_reason'])
|
||||
self.assertEqual(self.resource_name, event['logical_resource_id'])
|
||||
self.assertIsInstance(event, dict)
|
|
@ -33,8 +33,7 @@ class StacksTestJSON(base.BaseOrchestrationTest):
|
|||
|
||||
@attr(type='smoke')
|
||||
def test_stack_list_responds(self):
|
||||
resp, body = self.client.list_stacks()
|
||||
stacks = body['stacks']
|
||||
resp, stacks = self.client.list_stacks()
|
||||
self.assertEqual('200', resp['status'])
|
||||
self.assertIsInstance(stacks, list)
|
||||
|
||||
|
@ -42,9 +41,6 @@ class StacksTestJSON(base.BaseOrchestrationTest):
|
|||
def test_stack_crud_no_resources(self):
|
||||
stack_name = rand_name('heat')
|
||||
|
||||
# count how many stacks to start with
|
||||
resp, body = self.client.list_stacks()
|
||||
|
||||
# create the stack
|
||||
stack_identifier = self.create_stack(
|
||||
stack_name, self.empty_template)
|
||||
|
@ -54,21 +50,21 @@ class StacksTestJSON(base.BaseOrchestrationTest):
|
|||
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
|
||||
|
||||
# check for stack in list
|
||||
resp, body = self.client.list_stacks()
|
||||
list_ids = list([stack['id'] for stack in body['stacks']])
|
||||
resp, stacks = self.client.list_stacks()
|
||||
list_ids = list([stack['id'] for stack in stacks])
|
||||
self.assertIn(stack_id, list_ids)
|
||||
|
||||
# fetch the stack
|
||||
resp, body = self.client.get_stack(stack_identifier)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
resp, stack = self.client.get_stack(stack_identifier)
|
||||
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
|
||||
|
||||
# fetch the stack by name
|
||||
resp, body = self.client.get_stack(stack_name)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
resp, stack = self.client.get_stack(stack_name)
|
||||
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
|
||||
|
||||
# fetch the stack by id
|
||||
resp, body = self.client.get_stack(stack_id)
|
||||
self.assertEqual('CREATE_COMPLETE', body['stack_status'])
|
||||
resp, stack = self.client.get_stack(stack_id)
|
||||
self.assertEqual('CREATE_COMPLETE', stack['stack_status'])
|
||||
|
||||
# delete the stack
|
||||
resp = self.client.delete_stack(stack_identifier)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from tempest.api.orchestration import base
|
||||
from tempest.common.utils.data_utils import rand_name
|
||||
from tempest import exceptions
|
||||
from tempest.test import attr
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TemplateYAMLTestJSON(base.BaseOrchestrationTest):
|
||||
_interface = 'json'
|
||||
|
||||
template = """
|
||||
HeatTemplateFormatVersion: '2012-12-12'
|
||||
Description: |
|
||||
Template which creates only a new user
|
||||
Resources:
|
||||
CfnUser:
|
||||
Type: AWS::IAM::User
|
||||
"""
|
||||
|
||||
invalid_template_url = 'http://www.example.com/template.yaml'
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TemplateYAMLTestJSON, cls).setUpClass()
|
||||
cls.client = cls.orchestration_client
|
||||
cls.stack_name = 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 = {}
|
||||
|
||||
@attr(type='gate')
|
||||
def test_show_template(self):
|
||||
"""Getting template used to create the stack."""
|
||||
resp, template = self.client.show_template(self.stack_identifier)
|
||||
self.assertEqual('200', resp['status'])
|
||||
|
||||
@attr(type='gate')
|
||||
def test_validate_template(self):
|
||||
"""Validating template passing it content."""
|
||||
resp, parameters = self.client.validate_template(self.template,
|
||||
self.parameters)
|
||||
self.assertEqual('200', resp['status'])
|
||||
|
||||
@attr(type=['gate', 'negative'])
|
||||
def test_validate_template_url(self):
|
||||
"""Validating template passing url to it."""
|
||||
self.assertRaises(exceptions.BadRequest,
|
||||
self.client.validate_template_url,
|
||||
template_url=self.invalid_template_url,
|
||||
parameters=self.parameters)
|
||||
|
||||
|
||||
class TemplateAWSTestJSON(TemplateYAMLTestJSON):
|
||||
template = """
|
||||
{
|
||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||
"Description" : "Template which creates only a new user",
|
||||
"Resources" : {
|
||||
"CfnUser" : {
|
||||
"Type" : "AWS::IAM::User"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
invalid_template_url = 'http://www.example.com/template.template'
|
|
@ -42,7 +42,7 @@ class OrchestrationClient(rest_client.RestClient):
|
|||
|
||||
resp, body = self.get(uri)
|
||||
body = json.loads(body)
|
||||
return resp, body
|
||||
return resp, body['stacks']
|
||||
|
||||
def create_stack(self, name, disable_rollback=True, parameters={},
|
||||
timeout_mins=60, template=None, template_url=None):
|
||||
|
@ -176,3 +176,64 @@ class OrchestrationClient(rest_client.RestClient):
|
|||
(stack_name, status, self.build_timeout))
|
||||
raise exceptions.TimeoutException(message)
|
||||
time.sleep(self.build_interval)
|
||||
|
||||
def show_resource_metadata(self, stack_identifier, resource_name):
|
||||
"""Returns the resource's metadata."""
|
||||
url = ('stacks/{stack_identifier}/resources/{resource_name}'
|
||||
'/metadata'.format(**locals()))
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
return resp, body['metadata']
|
||||
|
||||
def list_events(self, stack_identifier):
|
||||
"""Returns list of all events for a stack."""
|
||||
url = 'stacks/{stack_identifier}/events'.format(**locals())
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
return resp, body['events']
|
||||
|
||||
def list_resource_events(self, stack_identifier, resource_name):
|
||||
"""Returns list of all events for a resource from stack."""
|
||||
url = ('stacks/{stack_identifier}/resources/{resource_name}'
|
||||
'/events'.format(**locals()))
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
return resp, body['events']
|
||||
|
||||
def show_event(self, stack_identifier, resource_name, event_id):
|
||||
"""Returns the details of a single stack's event."""
|
||||
url = ('stacks/{stack_identifier}/resources/{resource_name}/events'
|
||||
'/{event_id}'.format(**locals()))
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
return resp, body['event']
|
||||
|
||||
def show_template(self, stack_identifier):
|
||||
"""Returns the template for the stack."""
|
||||
url = ('stacks/{stack_identifier}/template'.format(**locals()))
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
return resp, body
|
||||
|
||||
def _validate_template(self, post_body):
|
||||
"""Returns the validation request result."""
|
||||
post_body = json.dumps(post_body)
|
||||
resp, body = self.post('validate', post_body, self.headers)
|
||||
body = json.loads(body)
|
||||
return resp, body
|
||||
|
||||
def validate_template(self, template, parameters={}):
|
||||
"""Returns the validation result for a template with parameters."""
|
||||
post_body = {
|
||||
'template': template,
|
||||
'parameters': parameters,
|
||||
}
|
||||
return self._validate_template(post_body)
|
||||
|
||||
def validate_template_url(self, template_url, parameters={}):
|
||||
"""Returns the validation result for a template with parameters."""
|
||||
post_body = {
|
||||
'template_url': template_url,
|
||||
'parameters': parameters,
|
||||
}
|
||||
return self._validate_template(post_body)
|
||||
|
|
Loading…
Reference in New Issue