Merge "Move signals to SignalResponder class"
This commit is contained in:
commit
8fe749e8a0
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import six
|
import six
|
||||||
import uuid
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
@ -315,63 +314,6 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
||||||
def _build_derived_options(self, action, source):
|
def _build_derived_options(self, action, source):
|
||||||
return source.get(sc.SoftwareConfig.OPTIONS)
|
return source.get(sc.SoftwareConfig.OPTIONS)
|
||||||
|
|
||||||
def _get_temp_url(self):
|
|
||||||
put_url = self.data().get('signal_temp_url')
|
|
||||||
if put_url:
|
|
||||||
return put_url
|
|
||||||
|
|
||||||
container = self.physical_resource_name()
|
|
||||||
object_name = str(uuid.uuid4())
|
|
||||||
|
|
||||||
self.client('swift').put_container(container)
|
|
||||||
|
|
||||||
put_url = self.client_plugin('swift').get_temp_url(
|
|
||||||
container, object_name)
|
|
||||||
self.data_set('signal_temp_url', put_url)
|
|
||||||
self.data_set('signal_object_name', object_name)
|
|
||||||
|
|
||||||
self.client('swift').put_object(
|
|
||||||
container, object_name, '')
|
|
||||||
return put_url
|
|
||||||
|
|
||||||
def _get_queue_id(self):
|
|
||||||
queue_id = self.data().get('signal_queue_id')
|
|
||||||
if queue_id:
|
|
||||||
return queue_id
|
|
||||||
|
|
||||||
queue_id = self.physical_resource_name()
|
|
||||||
zaqar = self.client('zaqar')
|
|
||||||
zaqar.queue(queue_id).ensure_exists()
|
|
||||||
self.data_set('signal_queue_id', queue_id)
|
|
||||||
return queue_id
|
|
||||||
|
|
||||||
def _delete_temp_url(self):
|
|
||||||
object_name = self.data().get('signal_object_name')
|
|
||||||
if not object_name:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
container = self.physical_resource_name()
|
|
||||||
swift = self.client('swift')
|
|
||||||
swift.delete_object(container, object_name)
|
|
||||||
headers = swift.head_container(container)
|
|
||||||
if int(headers['x-container-object-count']) == 0:
|
|
||||||
swift.delete_container(container)
|
|
||||||
except Exception as ex:
|
|
||||||
self.client_plugin('swift').ignore_not_found(ex)
|
|
||||||
self.data_delete('signal_object_name')
|
|
||||||
self.data_delete('signal_temp_url')
|
|
||||||
|
|
||||||
def _delete_queue(self):
|
|
||||||
queue_id = self.data().get('signal_queue_id')
|
|
||||||
if not queue_id:
|
|
||||||
return
|
|
||||||
zaqar = self.client('zaqar')
|
|
||||||
try:
|
|
||||||
zaqar.queue(queue_id).delete()
|
|
||||||
except Exception as ex:
|
|
||||||
self.client_plugin('zaqar').ignore_not_found(ex)
|
|
||||||
self.data_delete('signal_queue_id')
|
|
||||||
|
|
||||||
def _build_derived_inputs(self, action, source):
|
def _build_derived_inputs(self, action, source):
|
||||||
scl = sc.SoftwareConfig
|
scl = sc.SoftwareConfig
|
||||||
inputs = copy.deepcopy(source.get(scl.INPUTS)) or []
|
inputs = copy.deepcopy(source.get(scl.INPUTS)) or []
|
||||||
|
@ -440,7 +382,7 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
||||||
scl.DESCRIPTION: _('ID of signal to use for signaling '
|
scl.DESCRIPTION: _('ID of signal to use for signaling '
|
||||||
'output values'),
|
'output values'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self._get_temp_url()
|
'value': self._get_swift_signal_url()
|
||||||
})
|
})
|
||||||
inputs.append({
|
inputs.append({
|
||||||
scl.NAME: self.DEPLOY_SIGNAL_VERB,
|
scl.NAME: self.DEPLOY_SIGNAL_VERB,
|
||||||
|
@ -450,31 +392,32 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
||||||
'value': 'PUT'
|
'value': 'PUT'
|
||||||
})
|
})
|
||||||
elif self._signal_transport_heat() or self._signal_transport_zaqar():
|
elif self._signal_transport_heat() or self._signal_transport_zaqar():
|
||||||
|
creds = self._get_heat_signal_credentials()
|
||||||
inputs.extend([{
|
inputs.extend([{
|
||||||
scl.NAME: self.DEPLOY_AUTH_URL,
|
scl.NAME: self.DEPLOY_AUTH_URL,
|
||||||
scl.DESCRIPTION: _('URL for API authentication'),
|
scl.DESCRIPTION: _('URL for API authentication'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self.keystone().v3_endpoint
|
'value': creds['auth_url']
|
||||||
}, {
|
}, {
|
||||||
scl.NAME: self.DEPLOY_USERNAME,
|
scl.NAME: self.DEPLOY_USERNAME,
|
||||||
scl.DESCRIPTION: _('Username for API authentication'),
|
scl.DESCRIPTION: _('Username for API authentication'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self.physical_resource_name(),
|
'value': creds['username']
|
||||||
}, {
|
}, {
|
||||||
scl.NAME: self.DEPLOY_USER_ID,
|
scl.NAME: self.DEPLOY_USER_ID,
|
||||||
scl.DESCRIPTION: _('User ID for API authentication'),
|
scl.DESCRIPTION: _('User ID for API authentication'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self._get_user_id(),
|
'value': creds['user_id']
|
||||||
}, {
|
}, {
|
||||||
scl.NAME: self.DEPLOY_PASSWORD,
|
scl.NAME: self.DEPLOY_PASSWORD,
|
||||||
scl.DESCRIPTION: _('Password for API authentication'),
|
scl.DESCRIPTION: _('Password for API authentication'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self.password
|
'value': creds['password']
|
||||||
}, {
|
}, {
|
||||||
scl.NAME: self.DEPLOY_PROJECT_ID,
|
scl.NAME: self.DEPLOY_PROJECT_ID,
|
||||||
scl.DESCRIPTION: _('ID of project for API authentication'),
|
scl.DESCRIPTION: _('ID of project for API authentication'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self.stack.stack_user_project_id
|
'value': creds['project_id']
|
||||||
}])
|
}])
|
||||||
if self._signal_transport_zaqar():
|
if self._signal_transport_zaqar():
|
||||||
inputs.append({
|
inputs.append({
|
||||||
|
@ -482,31 +425,14 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
||||||
scl.DESCRIPTION: _('ID of queue to use for signaling '
|
scl.DESCRIPTION: _('ID of queue to use for signaling '
|
||||||
'output values'),
|
'output values'),
|
||||||
scl.TYPE: 'String',
|
scl.TYPE: 'String',
|
||||||
'value': self._get_queue_id()
|
'value': self._get_zaqar_signal_queue_id()
|
||||||
})
|
})
|
||||||
|
|
||||||
return inputs
|
return inputs
|
||||||
|
|
||||||
def handle_create(self):
|
def handle_create(self):
|
||||||
if self._signal_transport_cfn():
|
|
||||||
self._create_user()
|
|
||||||
self._create_keypair()
|
|
||||||
if self._signal_transport_heat() or self._signal_transport_zaqar():
|
|
||||||
self.password = uuid.uuid4().hex
|
|
||||||
self._create_user()
|
|
||||||
return self._handle_action(self.CREATE)
|
return self._handle_action(self.CREATE)
|
||||||
|
|
||||||
@property
|
|
||||||
def password(self):
|
|
||||||
return self.data().get('password')
|
|
||||||
|
|
||||||
@password.setter
|
|
||||||
def password(self, password):
|
|
||||||
if password is None:
|
|
||||||
self.data_delete('password')
|
|
||||||
else:
|
|
||||||
self.data_set('password', password, True)
|
|
||||||
|
|
||||||
def check_create_complete(self, sd):
|
def check_create_complete(self, sd):
|
||||||
if not sd:
|
if not sd:
|
||||||
return True
|
return True
|
||||||
|
@ -536,15 +462,8 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _delete_resource(self):
|
def _delete_resource(self):
|
||||||
if self._signal_transport_cfn():
|
self._delete_signals()
|
||||||
self._delete_ec2_signed_url()
|
self._delete_user()
|
||||||
self._delete_user()
|
|
||||||
elif self._signal_transport_heat():
|
|
||||||
self._delete_user()
|
|
||||||
elif self._signal_transport_temp_url():
|
|
||||||
self._delete_temp_url()
|
|
||||||
elif self._signal_transport_zaqar():
|
|
||||||
self._delete_queue()
|
|
||||||
|
|
||||||
derived_config_id = None
|
derived_config_id = None
|
||||||
if self.resource_id is not None:
|
if self.resource_id is not None:
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
from keystoneclient.contrib.ec2 import utils as ec2_utils
|
from keystoneclient.contrib.ec2 import utils as ec2_utils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
@ -36,17 +38,42 @@ class SignalResponder(stack_user.StackUser):
|
||||||
# API operations as a consequence of handling a signal
|
# API operations as a consequence of handling a signal
|
||||||
requires_deferred_auth = True
|
requires_deferred_auth = True
|
||||||
|
|
||||||
def handle_create(self):
|
|
||||||
super(SignalResponder, self).handle_create()
|
|
||||||
self._create_keypair()
|
|
||||||
|
|
||||||
def handle_delete(self):
|
def handle_delete(self):
|
||||||
|
self._delete_signals()
|
||||||
super(SignalResponder, self).handle_delete()
|
super(SignalResponder, self).handle_delete()
|
||||||
|
|
||||||
|
def _delete_signals(self):
|
||||||
self._delete_ec2_signed_url()
|
self._delete_ec2_signed_url()
|
||||||
self._delete_heat_signal_url()
|
self._delete_heat_signal_url()
|
||||||
|
self._delete_swift_signal_url()
|
||||||
|
self._delete_zaqar_signal_queue()
|
||||||
|
|
||||||
def _delete_ec2_signed_url(self):
|
@property
|
||||||
self.data_delete('ec2_signed_url')
|
def password(self):
|
||||||
|
return self.data().get('password')
|
||||||
|
|
||||||
|
@password.setter
|
||||||
|
def password(self, password):
|
||||||
|
if password is None:
|
||||||
|
self.data_delete('password')
|
||||||
|
else:
|
||||||
|
self.data_set('password', password, True)
|
||||||
|
|
||||||
|
def _get_heat_signal_credentials(self):
|
||||||
|
"""Return OpenStack credentials that can be used to send a signal.
|
||||||
|
|
||||||
|
These credentials are for the user associated with this resource in
|
||||||
|
the heat stack user domain.
|
||||||
|
"""
|
||||||
|
if self._get_user_id() is None:
|
||||||
|
if self.password is None:
|
||||||
|
self.password = uuid.uuid4().hex
|
||||||
|
self._create_user()
|
||||||
|
return {'auth_url': self.keystone().v3_endpoint,
|
||||||
|
'username': self.physical_resource_name(),
|
||||||
|
'user_id': self._get_user_id(),
|
||||||
|
'password': self.password,
|
||||||
|
'project_id': self.stack.stack_user_project_id}
|
||||||
|
|
||||||
def _get_ec2_signed_url(self, signal_type=SIGNAL):
|
def _get_ec2_signed_url(self, signal_type=SIGNAL):
|
||||||
"""Create properly formatted and pre-signed URL.
|
"""Create properly formatted and pre-signed URL.
|
||||||
|
@ -65,9 +92,19 @@ class SignalResponder(stack_user.StackUser):
|
||||||
secret_key = self.data().get('secret_key')
|
secret_key = self.data().get('secret_key')
|
||||||
|
|
||||||
if not access_key or not secret_key:
|
if not access_key or not secret_key:
|
||||||
LOG.warn(_LW('Cannot generate signed url, '
|
if self.id is None or self.action == self.DELETE:
|
||||||
'no stored access/secret key'))
|
# it is either too early or too late to do this
|
||||||
return
|
return
|
||||||
|
if self._get_user_id() is None:
|
||||||
|
self._create_user()
|
||||||
|
self._create_keypair()
|
||||||
|
access_key = self.data().get('access_key')
|
||||||
|
secret_key = self.data().get('secret_key')
|
||||||
|
|
||||||
|
if not access_key or not secret_key:
|
||||||
|
LOG.warn(_LW('Cannot generate signed url, '
|
||||||
|
'unable to create keypair'))
|
||||||
|
return
|
||||||
|
|
||||||
config_url = cfg.CONF.heat_waitcondition_server_url
|
config_url = cfg.CONF.heat_waitcondition_server_url
|
||||||
if config_url:
|
if config_url:
|
||||||
|
@ -106,14 +143,23 @@ class SignalResponder(stack_user.StackUser):
|
||||||
self.data_set('ec2_signed_url', url)
|
self.data_set('ec2_signed_url', url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def _delete_heat_signal_url(self):
|
def _delete_ec2_signed_url(self):
|
||||||
self.data_delete('heat_signal_url')
|
self.data_delete('ec2_signed_url')
|
||||||
|
self._delete_keypair()
|
||||||
|
|
||||||
def _get_heat_signal_url(self):
|
def _get_heat_signal_url(self):
|
||||||
|
"""Return a heat-api signal URL for this resource.
|
||||||
|
|
||||||
|
This URL is not pre-signed, valid user credentials are required.
|
||||||
|
"""
|
||||||
stored = self.data().get('heat_signal_url')
|
stored = self.data().get('heat_signal_url')
|
||||||
if stored is not None:
|
if stored is not None:
|
||||||
return stored
|
return stored
|
||||||
|
|
||||||
|
if self.id is None or self.action == self.DELETE:
|
||||||
|
# it is either too early or too late to do this
|
||||||
|
return
|
||||||
|
|
||||||
url = self.client_plugin('heat').get_heat_url()
|
url = self.client_plugin('heat').get_heat_url()
|
||||||
host_url = urlparse.urlparse(url)
|
host_url = urlparse.urlparse(url)
|
||||||
path = self.identifier().url_path()
|
path = self.identifier().url_path()
|
||||||
|
@ -123,3 +169,84 @@ class SignalResponder(stack_user.StackUser):
|
||||||
|
|
||||||
self.data_set('heat_signal_url', url)
|
self.data_set('heat_signal_url', url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
def _delete_heat_signal_url(self):
|
||||||
|
self.data_delete('heat_signal_url')
|
||||||
|
|
||||||
|
def _get_swift_signal_url(self):
|
||||||
|
"""Create properly formatted and pre-signed Swift signal URL.
|
||||||
|
|
||||||
|
This uses a Swift pre-signed temp_url.
|
||||||
|
"""
|
||||||
|
put_url = self.data().get('swift_signal_url')
|
||||||
|
if put_url:
|
||||||
|
return put_url
|
||||||
|
|
||||||
|
if self.id is None or self.action == self.DELETE:
|
||||||
|
# it is either too early or too late to do this
|
||||||
|
return
|
||||||
|
|
||||||
|
container = self.stack.id
|
||||||
|
object_name = self.physical_resource_name()
|
||||||
|
|
||||||
|
self.client('swift').put_container(container)
|
||||||
|
|
||||||
|
put_url = self.client_plugin('swift').get_temp_url(
|
||||||
|
container, object_name)
|
||||||
|
self.data_set('swift_signal_url', put_url)
|
||||||
|
self.data_set('swift_signal_object_name', object_name)
|
||||||
|
|
||||||
|
self.client('swift').put_object(
|
||||||
|
container, object_name, '')
|
||||||
|
return put_url
|
||||||
|
|
||||||
|
def _delete_swift_signal_url(self):
|
||||||
|
object_name = self.data().get('swift_signal_object_name')
|
||||||
|
if not object_name:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
container = self.physical_resource_name()
|
||||||
|
swift = self.client('swift')
|
||||||
|
swift.delete_object(container, object_name)
|
||||||
|
headers = swift.head_container(container)
|
||||||
|
if int(headers['x-container-object-count']) == 0:
|
||||||
|
swift.delete_container(container)
|
||||||
|
except Exception as ex:
|
||||||
|
self.client_plugin('swift').ignore_not_found(ex)
|
||||||
|
self.data_delete('swift_signal_object_name')
|
||||||
|
self.data_delete('swift_signal_url')
|
||||||
|
|
||||||
|
def _get_zaqar_signal_queue_id(self):
|
||||||
|
"""Return a zaqar queue_id for signaling this resource.
|
||||||
|
|
||||||
|
This uses the created user for the credentials.
|
||||||
|
"""
|
||||||
|
queue_id = self.data().get('zaqar_signal_queue_id')
|
||||||
|
if queue_id:
|
||||||
|
return queue_id
|
||||||
|
|
||||||
|
if self.id is None or self.action == self.DELETE:
|
||||||
|
# it is either too early or too late to do this
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._get_user_id() is None:
|
||||||
|
if self.password is None:
|
||||||
|
self.password = uuid.uuid4().hex
|
||||||
|
self._create_user()
|
||||||
|
|
||||||
|
queue_id = self.physical_resource_name()
|
||||||
|
zaqar = self.client('zaqar')
|
||||||
|
zaqar.queue(queue_id).ensure_exists()
|
||||||
|
self.data_set('zaqar_signal_queue_id', queue_id)
|
||||||
|
return queue_id
|
||||||
|
|
||||||
|
def _delete_zaqar_signal_queue(self):
|
||||||
|
queue_id = self.data().get('zaqar_signal_queue_id')
|
||||||
|
if not queue_id:
|
||||||
|
return
|
||||||
|
zaqar = self.client('zaqar')
|
||||||
|
try:
|
||||||
|
zaqar.queue(queue_id).delete()
|
||||||
|
except Exception as ex:
|
||||||
|
self.client_plugin('zaqar').ignore_not_found(ex)
|
||||||
|
self.data_delete('zaqar_signal_queue_id')
|
||||||
|
|
|
@ -25,7 +25,7 @@ LOG = logging.getLogger(__name__)
|
||||||
class StackUser(resource.Resource):
|
class StackUser(resource.Resource):
|
||||||
|
|
||||||
# Subclasses create a user, and optionally keypair associated with a
|
# Subclasses create a user, and optionally keypair associated with a
|
||||||
# resource in a stack. Users are created in the heat stack user domain
|
# resource in a stack. Users are created in the heat stack user domain
|
||||||
# (in a project specific to the stack)
|
# (in a project specific to the stack)
|
||||||
def __init__(self, name, json_snippet, stack):
|
def __init__(self, name, json_snippet, stack):
|
||||||
super(StackUser, self).__init__(name, json_snippet, stack)
|
super(StackUser, self).__init__(name, json_snippet, stack)
|
||||||
|
@ -34,6 +34,10 @@ class StackUser(resource.Resource):
|
||||||
self._create_user()
|
self._create_user()
|
||||||
|
|
||||||
def _create_user(self):
|
def _create_user(self):
|
||||||
|
if self.data().get('user_id'):
|
||||||
|
# a user has been created already
|
||||||
|
return
|
||||||
|
|
||||||
# Check for stack user project, create if not yet set
|
# Check for stack user project, create if not yet set
|
||||||
if not self.stack.stack_user_project_id:
|
if not self.stack.stack_user_project_id:
|
||||||
project_id = self.keystone().create_stack_domain_project(
|
project_id = self.keystone().create_stack_domain_project(
|
||||||
|
@ -85,6 +89,10 @@ class StackUser(resource.Resource):
|
||||||
user_id = self._get_user_id()
|
user_id = self._get_user_id()
|
||||||
if user_id is None:
|
if user_id is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# the user is going away, so we want the keypair gone as well
|
||||||
|
self._delete_keypair()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.keystone().delete_stack_domain_user(
|
self.keystone().delete_stack_domain_user(
|
||||||
user_id=user_id, project_id=self.stack.stack_user_project_id)
|
user_id=user_id, project_id=self.stack.stack_user_project_id)
|
||||||
|
@ -100,8 +108,7 @@ class StackUser(resource.Resource):
|
||||||
self.keystone().delete_stack_user(user_id)
|
self.keystone().delete_stack_user(user_id)
|
||||||
except kc_exception.NotFound:
|
except kc_exception.NotFound:
|
||||||
pass
|
pass
|
||||||
for data_key in ('credential_id', 'access_key', 'secret_key'):
|
self.data_delete('user_id')
|
||||||
self.data_delete(data_key)
|
|
||||||
|
|
||||||
def handle_suspend(self):
|
def handle_suspend(self):
|
||||||
user_id = self._get_user_id()
|
user_id = self._get_user_id()
|
||||||
|
@ -125,6 +132,9 @@ class StackUser(resource.Resource):
|
||||||
# Subclasses may optionally call this in handle_create to create
|
# Subclasses may optionally call this in handle_create to create
|
||||||
# an ec2 keypair associated with the user, the resulting keys are
|
# an ec2 keypair associated with the user, the resulting keys are
|
||||||
# stored in resource_data
|
# stored in resource_data
|
||||||
|
if self.data().get('credential_id'):
|
||||||
|
return # a keypair was created already
|
||||||
|
|
||||||
user_id = self._get_user_id()
|
user_id = self._get_user_id()
|
||||||
kp = self.keystone().create_stack_domain_user_keypair(
|
kp = self.keystone().create_stack_domain_user_keypair(
|
||||||
user_id=user_id, project_id=self.stack.stack_user_project_id)
|
user_id=user_id, project_id=self.stack.stack_user_project_id)
|
||||||
|
@ -146,10 +156,12 @@ class StackUser(resource.Resource):
|
||||||
def _delete_keypair(self):
|
def _delete_keypair(self):
|
||||||
# Subclasses may optionally call this to delete a keypair created
|
# Subclasses may optionally call this to delete a keypair created
|
||||||
# via _create_keypair
|
# via _create_keypair
|
||||||
user_id = self._get_user_id()
|
|
||||||
credential_id = self.data().get('credential_id')
|
credential_id = self.data().get('credential_id')
|
||||||
if not credential_id:
|
if not credential_id:
|
||||||
return
|
return
|
||||||
|
user_id = self._get_user_id()
|
||||||
|
if user_id is None:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.keystone().delete_stack_domain_user_keypair(
|
self.keystone().delete_stack_domain_user_keypair(
|
||||||
|
|
|
@ -109,6 +109,7 @@ class FakeKeystoneClient(object):
|
||||||
self.credential_id = credential_id
|
self.credential_id = credential_id
|
||||||
self.token = auth_token
|
self.token = auth_token
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.v3_endpoint = 'http://localhost:5000/v3'
|
||||||
|
|
||||||
class FakeCred(object):
|
class FakeCred(object):
|
||||||
id = self.credential_id
|
id = self.credential_id
|
||||||
|
|
|
@ -136,8 +136,11 @@ class ResourceWithRequiredProps(GenericResource):
|
||||||
|
|
||||||
|
|
||||||
class SignalResource(signal_responder.SignalResponder):
|
class SignalResource(signal_responder.SignalResponder):
|
||||||
properties_schema = {}
|
properties_schema = {
|
||||||
attributes_schema = {'AlarmUrl': attributes.Schema('Get a signed webhook')}
|
'signal_transport': properties.Schema(properties.Schema.STRING,
|
||||||
|
default='CFN_SIGNAL')}
|
||||||
|
attributes_schema = {'AlarmUrl': attributes.Schema('Get a signed webhook'),
|
||||||
|
'signal': attributes.Schema('Get a signal')}
|
||||||
|
|
||||||
def handle_create(self):
|
def handle_create(self):
|
||||||
super(SignalResource, self).handle_create()
|
super(SignalResource, self).handle_create()
|
||||||
|
@ -148,8 +151,22 @@ class SignalResource(signal_responder.SignalResponder):
|
||||||
{'type': self.type(), 'details': details})
|
{'type': self.type(), 'details': details})
|
||||||
|
|
||||||
def _resolve_attribute(self, name):
|
def _resolve_attribute(self, name):
|
||||||
if name == 'AlarmUrl' and self.resource_id is not None:
|
if self.resource_id is not None:
|
||||||
return six.text_type(self._get_ec2_signed_url())
|
if self.properties['signal_transport'] == 'CFN_SIGNAL':
|
||||||
|
d = {'alarm_url': six.text_type(self._get_ec2_signed_url())}
|
||||||
|
elif self.properties['signal_transport'] == 'HEAT_SIGNAL':
|
||||||
|
d = self._get_heat_signal_credentials()
|
||||||
|
d['alarm_url'] = six.text_type(self._get_heat_signal_url())
|
||||||
|
elif self.properties['signal_transport'] == 'TEMP_URL_SIGNAL':
|
||||||
|
d = {'alarm_url': six.text_type(self._get_swift_signal_url())}
|
||||||
|
elif self.properties['signal_transport'] == 'ZAQAR_SIGNAL':
|
||||||
|
d = self._get_heat_signal_credentials()
|
||||||
|
d['queue_id'] = six.text_type(
|
||||||
|
self._get_zaqar_signal_queue_id())
|
||||||
|
if name == 'AlarmUrl':
|
||||||
|
return d['alarm_url']
|
||||||
|
elif name == 'signal':
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
class StackUserResource(stack_user.StackUser):
|
class StackUserResource(stack_user.StackUser):
|
||||||
|
|
|
@ -12,14 +12,15 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import six
|
import uuid
|
||||||
|
|
||||||
from keystoneclient import exceptions as kc_exceptions
|
from keystoneclient import exceptions as kc_exceptions
|
||||||
|
import mox
|
||||||
|
import six
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine.resources import stack_user
|
|
||||||
from heat.engine import scheduler
|
from heat.engine import scheduler
|
||||||
from heat.engine import stack as parser
|
from heat.engine import stack as parser
|
||||||
from heat.engine import template
|
from heat.engine import template
|
||||||
|
@ -30,13 +31,53 @@ from heat.tests import generic_resource
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
|
|
||||||
|
|
||||||
test_template_signal = '''
|
test_cfn_template_signal = '''
|
||||||
{
|
{
|
||||||
"AWSTemplateFormatVersion" : "2010-09-09",
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||||
"Description" : "Just a test.",
|
"Description" : "Just a test.",
|
||||||
"Parameters" : {},
|
"Parameters" : {},
|
||||||
"Resources" : {
|
"Resources" : {
|
||||||
"signal_handler" : {"Type" : "SignalResourceType"},
|
"signal_handler" : {"Type" : "SignalResourceType",
|
||||||
|
"Properties": {"signal_transport": "CFN_SIGNAL"}},
|
||||||
|
"resource_X" : {"Type" : "GenericResourceType"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
test_heat_template_signal = '''
|
||||||
|
{
|
||||||
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||||
|
"Description" : "Just a test.",
|
||||||
|
"Parameters" : {},
|
||||||
|
"Resources" : {
|
||||||
|
"signal_handler" : {"Type" : "SignalResourceType",
|
||||||
|
"Properties": {"signal_transport": "HEAT_SIGNAL"}},
|
||||||
|
"resource_X" : {"Type" : "GenericResourceType"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
test_swift_template_signal = '''
|
||||||
|
{
|
||||||
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||||
|
"Description" : "Just a test.",
|
||||||
|
"Parameters" : {},
|
||||||
|
"Resources" : {
|
||||||
|
"signal_handler" : {"Type" : "SignalResourceType",
|
||||||
|
"Properties": {"signal_transport": "TEMP_URL_SIGNAL"}},
|
||||||
|
"resource_X" : {"Type" : "GenericResourceType"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
test_zaqar_template_signal = '''
|
||||||
|
{
|
||||||
|
"AWSTemplateFormatVersion" : "2010-09-09",
|
||||||
|
"Description" : "Just a test.",
|
||||||
|
"Parameters" : {},
|
||||||
|
"Resources" : {
|
||||||
|
"signal_handler" : {"Type" : "SignalResourceType",
|
||||||
|
"Properties": {"signal_transport": "ZAQAR_SIGNAL"}},
|
||||||
"resource_X" : {"Type" : "GenericResourceType"}
|
"resource_X" : {"Type" : "GenericResourceType"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,11 +93,12 @@ class SignalTest(common.HeatTestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(SignalTest, self).tearDown()
|
super(SignalTest, self).tearDown()
|
||||||
|
|
||||||
def create_stack(self, stack_name='test_stack', stub=True):
|
def create_stack(self, templ=test_cfn_template_signal,
|
||||||
templ = template.Template(template_format.parse(test_template_signal))
|
stack_name='test_stack', stub=True):
|
||||||
|
tpl = template.Template(template_format.parse(templ))
|
||||||
ctx = utils.dummy_context()
|
ctx = utils.dummy_context()
|
||||||
ctx.tenant_id = 'test_tenant'
|
ctx.tenant_id = 'test_tenant'
|
||||||
stack = parser.Stack(ctx, stack_name, templ,
|
stack = parser.Stack(ctx, stack_name, tpl,
|
||||||
disable_rollback=True)
|
disable_rollback=True)
|
||||||
|
|
||||||
# Stub out the stack ID so we have a known value
|
# Stub out the stack ID so we have a known value
|
||||||
|
@ -67,23 +109,6 @@ class SignalTest(common.HeatTestCase):
|
||||||
|
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
def test_handle_create_fail_keypair_raise(self):
|
|
||||||
self.stack = self.create_stack(stack_name='create_fail_keypair')
|
|
||||||
|
|
||||||
self.m.StubOutWithMock(stack_user.StackUser, '_create_keypair')
|
|
||||||
stack_user.StackUser._create_keypair().AndRaise(Exception('Failed'))
|
|
||||||
self.m.ReplayAll()
|
|
||||||
|
|
||||||
self.stack.create()
|
|
||||||
|
|
||||||
rsrc = self.stack['signal_handler']
|
|
||||||
rs_data = resource_data_object.ResourceData.get_all(rsrc)
|
|
||||||
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
|
|
||||||
self.assertIn('Failed', rsrc.status_reason)
|
|
||||||
self.assertEqual('1234', rs_data.get('user_id'))
|
|
||||||
self.assertIsNone(rsrc.resource_id)
|
|
||||||
self.m.VerifyAll()
|
|
||||||
|
|
||||||
def test_resource_data(self):
|
def test_resource_data(self):
|
||||||
self.stub_keystoneclient(
|
self.stub_keystoneclient(
|
||||||
access='anaccesskey',
|
access='anaccesskey',
|
||||||
|
@ -97,6 +122,7 @@ class SignalTest(common.HeatTestCase):
|
||||||
|
|
||||||
rsrc = self.stack['signal_handler']
|
rsrc = self.stack['signal_handler']
|
||||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
rsrc._create_keypair()
|
||||||
|
|
||||||
# Ensure the resource data has been stored correctly
|
# Ensure the resource data has been stored correctly
|
||||||
rs_data = resource_data_object.ResourceData.get_all(rsrc)
|
rs_data = resource_data_object.ResourceData.get_all(rsrc)
|
||||||
|
@ -174,8 +200,131 @@ class SignalTest(common.HeatTestCase):
|
||||||
rsrc = self.stack['signal_handler']
|
rsrc = self.stack['signal_handler']
|
||||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
first_url = rsrc.FnGetAtt('AlarmUrl')
|
first_url = rsrc.FnGetAtt('signal')
|
||||||
second_url = rsrc.FnGetAtt('AlarmUrl')
|
second_url = rsrc.FnGetAtt('signal')
|
||||||
|
self.assertEqual(first_url, second_url)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Heat_Signal(self):
|
||||||
|
self.stack = self.create_stack(test_heat_template_signal)
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client_plugin('heat'),
|
||||||
|
'get_heat_url')
|
||||||
|
|
||||||
|
self.stack.clients.client_plugin('heat').get_heat_url().AndReturn(
|
||||||
|
'http://server.test:8004/v1')
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
signal = rsrc.FnGetAtt('signal')
|
||||||
|
self.assertEqual('http://localhost:5000/v3', signal['auth_url'])
|
||||||
|
self.assertEqual('aprojectid', signal['project_id'])
|
||||||
|
self.assertEqual('1234', signal['user_id'])
|
||||||
|
self.assertIn('username', signal)
|
||||||
|
self.assertIn('password', signal)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Heat_Signal_is_cached(self):
|
||||||
|
self.stack = self.create_stack(test_heat_template_signal)
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
first_url = rsrc.FnGetAtt('signal')
|
||||||
|
second_url = rsrc.FnGetAtt('signal')
|
||||||
|
self.assertEqual(first_url, second_url)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Zaqar_Signal(self):
|
||||||
|
self.stack = self.create_stack(test_zaqar_template_signal)
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
signal = rsrc.FnGetAtt('signal')
|
||||||
|
self.assertEqual('http://localhost:5000/v3', signal['auth_url'])
|
||||||
|
self.assertEqual('aprojectid', signal['project_id'])
|
||||||
|
self.assertEqual('1234', signal['user_id'])
|
||||||
|
self.assertIn('username', signal)
|
||||||
|
self.assertIn('password', signal)
|
||||||
|
self.assertIn('queue_id', signal)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Zaqar_Signal_is_cached(self):
|
||||||
|
self.stack = self.create_stack(test_zaqar_template_signal)
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
first_url = rsrc.FnGetAtt('signal')
|
||||||
|
second_url = rsrc.FnGetAtt('signal')
|
||||||
|
self.assertEqual(first_url, second_url)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Swift_Signal(self):
|
||||||
|
self.stack = self.create_stack(test_swift_template_signal)
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client('swift'),
|
||||||
|
'put_container')
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client('swift'),
|
||||||
|
'put_object')
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client_plugin('swift'),
|
||||||
|
'get_temp_url')
|
||||||
|
|
||||||
|
self.stack.clients.client('swift').put_container(
|
||||||
|
mox.IgnoreArg()).AndReturn(None)
|
||||||
|
self.stack.clients.client_plugin('swift').get_temp_url(
|
||||||
|
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
|
||||||
|
'http://192.0.2.1/v1/AUTH_aprojectid/foo/bar')
|
||||||
|
self.stack.clients.client('swift').put_object(
|
||||||
|
mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None)
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
self.assertEqual('http://192.0.2.1/v1/AUTH_aprojectid/foo/bar',
|
||||||
|
rsrc.FnGetAtt('AlarmUrl'))
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_FnGetAtt_Swift_Signal_is_cached(self):
|
||||||
|
self.stack = self.create_stack(test_swift_template_signal)
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client('swift'),
|
||||||
|
'put_container')
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client('swift'),
|
||||||
|
'put_object')
|
||||||
|
self.m.StubOutWithMock(self.stack.clients.client_plugin('swift'),
|
||||||
|
'get_temp_url')
|
||||||
|
|
||||||
|
self.stack.clients.client('swift').put_container(
|
||||||
|
mox.IgnoreArg()).AndReturn(None)
|
||||||
|
self.stack.clients.client_plugin('swift').get_temp_url(
|
||||||
|
mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
|
||||||
|
'http://192.0.2.1/v1/AUTH_aprojectid/foo/' + uuid.uuid4().hex)
|
||||||
|
self.stack.clients.client('swift').put_object(
|
||||||
|
mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(None)
|
||||||
|
|
||||||
|
self.m.ReplayAll()
|
||||||
|
self.stack.create()
|
||||||
|
|
||||||
|
rsrc = self.stack['signal_handler']
|
||||||
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
|
first_url = rsrc.FnGetAtt('signal')
|
||||||
|
second_url = rsrc.FnGetAtt('signal')
|
||||||
self.assertEqual(first_url, second_url)
|
self.assertEqual(first_url, second_url)
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
@ -190,6 +339,7 @@ class SignalTest(common.HeatTestCase):
|
||||||
self.stack.create()
|
self.stack.create()
|
||||||
|
|
||||||
rsrc = self.stack['signal_handler']
|
rsrc = self.stack['signal_handler']
|
||||||
|
rsrc.resource_id_set('signal')
|
||||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||||
|
|
||||||
self.assertIn('http://server.test:8000/v1/signal',
|
self.assertIn('http://server.test:8000/v1/signal',
|
||||||
|
|
|
@ -979,22 +979,22 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||||
self.deployment.id = 23
|
self.deployment.id = 23
|
||||||
self.deployment.uuid = str(uuid.uuid4())
|
self.deployment.uuid = str(uuid.uuid4())
|
||||||
self.deployment.action = self.deployment.CREATE
|
self.deployment.action = self.deployment.CREATE
|
||||||
container = self.deployment.physical_resource_name()
|
object_name = self.deployment.physical_resource_name()
|
||||||
|
|
||||||
temp_url = self.deployment._get_temp_url()
|
temp_url = self.deployment._get_swift_signal_url()
|
||||||
temp_url_pattern = re.compile(
|
temp_url_pattern = re.compile(
|
||||||
'^http://192.0.2.1/v1/AUTH_test_tenant_id/'
|
'^http://192.0.2.1/v1/AUTH_test_tenant_id/'
|
||||||
'(software_deployment_test_stack-deployment_mysql-.*)/(.*)'
|
'(.*)/(software_deployment_test_stack-deployment_mysql-.*)'
|
||||||
'\\?temp_url_sig=.*&temp_url_expires=\\d*$')
|
'\\?temp_url_sig=.*&temp_url_expires=\\d*$')
|
||||||
self.assertRegex(temp_url, temp_url_pattern)
|
self.assertRegex(temp_url, temp_url_pattern)
|
||||||
m = temp_url_pattern.search(temp_url)
|
m = temp_url_pattern.search(temp_url)
|
||||||
object_name = m.group(2)
|
container = m.group(1)
|
||||||
self.assertEqual(container, m.group(1))
|
self.assertEqual(object_name, m.group(2))
|
||||||
self.assertEqual(dep_data['signal_object_name'], object_name)
|
self.assertEqual(dep_data['swift_signal_object_name'], object_name)
|
||||||
|
|
||||||
self.assertEqual(dep_data['signal_temp_url'], temp_url)
|
self.assertEqual(dep_data['swift_signal_url'], temp_url)
|
||||||
|
|
||||||
self.assertEqual(temp_url, self.deployment._get_temp_url())
|
self.assertEqual(temp_url, self.deployment._get_swift_signal_url())
|
||||||
|
|
||||||
sc.put_container.assert_called_once_with(container)
|
sc.put_container.assert_called_once_with(container)
|
||||||
sc.put_object.assert_called_once_with(container, object_name, '')
|
sc.put_object.assert_called_once_with(container, object_name, '')
|
||||||
|
@ -1002,7 +1002,7 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||||
def test_delete_temp_url(self):
|
def test_delete_temp_url(self):
|
||||||
object_name = str(uuid.uuid4())
|
object_name = str(uuid.uuid4())
|
||||||
dep_data = {
|
dep_data = {
|
||||||
'signal_object_name': object_name
|
'swift_signal_object_name': object_name
|
||||||
}
|
}
|
||||||
self._create_stack(self.template_temp_url_signal)
|
self._create_stack(self.template_temp_url_signal)
|
||||||
|
|
||||||
|
@ -1021,31 +1021,34 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||||
self.deployment.id = 23
|
self.deployment.id = 23
|
||||||
self.deployment.uuid = str(uuid.uuid4())
|
self.deployment.uuid = str(uuid.uuid4())
|
||||||
container = self.deployment.physical_resource_name()
|
container = self.deployment.physical_resource_name()
|
||||||
self.deployment._delete_temp_url()
|
self.deployment._delete_swift_signal_url()
|
||||||
sc.delete_object.assert_called_once_with(container, object_name)
|
sc.delete_object.assert_called_once_with(container, object_name)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[mock.call('signal_object_name'), mock.call('signal_temp_url')],
|
[mock.call('swift_signal_object_name'),
|
||||||
|
mock.call('swift_signal_url')],
|
||||||
self.deployment.data_delete.mock_calls)
|
self.deployment.data_delete.mock_calls)
|
||||||
|
|
||||||
swift_exc = swift.SwiftClientPlugin.exceptions_module
|
swift_exc = swift.SwiftClientPlugin.exceptions_module
|
||||||
sc.delete_object.side_effect = swift_exc.ClientException(
|
sc.delete_object.side_effect = swift_exc.ClientException(
|
||||||
'Not found', http_status=404)
|
'Not found', http_status=404)
|
||||||
self.deployment._delete_temp_url()
|
self.deployment._delete_swift_signal_url()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[mock.call('signal_object_name'), mock.call('signal_temp_url'),
|
[mock.call('swift_signal_object_name'),
|
||||||
mock.call('signal_object_name'), mock.call('signal_temp_url')],
|
mock.call('swift_signal_url'),
|
||||||
|
mock.call('swift_signal_object_name'),
|
||||||
|
mock.call('swift_signal_url')],
|
||||||
self.deployment.data_delete.mock_calls)
|
self.deployment.data_delete.mock_calls)
|
||||||
|
|
||||||
del(dep_data['signal_object_name'])
|
del(dep_data['swift_signal_object_name'])
|
||||||
self.deployment.physical_resource_name = mock.Mock()
|
self.deployment.physical_resource_name = mock.Mock()
|
||||||
self.deployment._delete_temp_url()
|
self.deployment._delete_swift_signal_url()
|
||||||
self.assertFalse(self.deployment.physical_resource_name.called)
|
self.assertFalse(self.deployment.physical_resource_name.called)
|
||||||
|
|
||||||
def test_handle_action_temp_url(self):
|
def test_handle_action_temp_url(self):
|
||||||
|
|
||||||
self._create_stack(self.template_temp_url_signal)
|
self._create_stack(self.template_temp_url_signal)
|
||||||
dep_data = {
|
dep_data = {
|
||||||
'signal_temp_url': (
|
'swift_signal_url': (
|
||||||
'http://192.0.2.1/v1/AUTH_a/b/c'
|
'http://192.0.2.1/v1/AUTH_a/b/c'
|
||||||
'?temp_url_sig=ctemp_url_expires=1234')
|
'?temp_url_sig=ctemp_url_expires=1234')
|
||||||
}
|
}
|
||||||
|
@ -1079,17 +1082,18 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||||
self.deployment.uuid = str(uuid.uuid4())
|
self.deployment.uuid = str(uuid.uuid4())
|
||||||
self.deployment.action = self.deployment.CREATE
|
self.deployment.action = self.deployment.CREATE
|
||||||
|
|
||||||
queue_id = self.deployment._get_queue_id()
|
queue_id = self.deployment._get_zaqar_signal_queue_id()
|
||||||
self.assertEqual(2, len(zc.queue.mock_calls))
|
self.assertEqual(2, len(zc.queue.mock_calls))
|
||||||
self.assertEqual(queue_id, zc.queue.mock_calls[0][1][0])
|
self.assertEqual(queue_id, zc.queue.mock_calls[0][1][0])
|
||||||
self.assertEqual(queue_id, dep_data['signal_queue_id'])
|
self.assertEqual(queue_id, dep_data['zaqar_signal_queue_id'])
|
||||||
|
|
||||||
self.assertEqual(queue_id, self.deployment._get_queue_id())
|
self.assertEqual(queue_id,
|
||||||
|
self.deployment._get_zaqar_signal_queue_id())
|
||||||
|
|
||||||
def test_delete_zaqar_queue(self):
|
def test_delete_zaqar_queue(self):
|
||||||
queue_id = str(uuid.uuid4())
|
queue_id = str(uuid.uuid4())
|
||||||
dep_data = {
|
dep_data = {
|
||||||
'signal_queue_id': queue_id
|
'zaqar_signal_queue_id': queue_id
|
||||||
}
|
}
|
||||||
self._create_stack(self.template_zaqar_signal)
|
self._create_stack(self.template_zaqar_signal)
|
||||||
|
|
||||||
|
@ -1103,23 +1107,24 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
||||||
|
|
||||||
self.deployment.id = 23
|
self.deployment.id = 23
|
||||||
self.deployment.uuid = str(uuid.uuid4())
|
self.deployment.uuid = str(uuid.uuid4())
|
||||||
self.deployment._delete_queue()
|
self.deployment._delete_zaqar_signal_queue()
|
||||||
zc.queue.assert_called_once_with(queue_id)
|
zc.queue.assert_called_once_with(queue_id)
|
||||||
self.assertTrue(zc.queue(self.deployment.uuid).delete.called)
|
self.assertTrue(zc.queue(self.deployment.uuid).delete.called)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[mock.call('signal_queue_id')],
|
[mock.call('zaqar_signal_queue_id')],
|
||||||
self.deployment.data_delete.mock_calls)
|
self.deployment.data_delete.mock_calls)
|
||||||
|
|
||||||
zaqar_exc = zaqar.ZaqarClientPlugin.exceptions_module
|
zaqar_exc = zaqar.ZaqarClientPlugin.exceptions_module
|
||||||
zc.queue.delete.side_effect = zaqar_exc.ResourceNotFound()
|
zc.queue.delete.side_effect = zaqar_exc.ResourceNotFound()
|
||||||
self.deployment._delete_queue()
|
self.deployment._delete_zaqar_signal_queue()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[mock.call('signal_queue_id'), mock.call('signal_queue_id')],
|
[mock.call('zaqar_signal_queue_id'),
|
||||||
|
mock.call('zaqar_signal_queue_id')],
|
||||||
self.deployment.data_delete.mock_calls)
|
self.deployment.data_delete.mock_calls)
|
||||||
|
|
||||||
dep_data.pop('signal_queue_id')
|
dep_data.pop('zaqar_signal_queue_id')
|
||||||
self.deployment.physical_resource_name = mock.Mock()
|
self.deployment.physical_resource_name = mock.Mock()
|
||||||
self.deployment._delete_queue()
|
self.deployment._delete_zaqar_signal_queue()
|
||||||
self.assertEqual(2, len(self.deployment.data_delete.mock_calls))
|
self.assertEqual(2, len(self.deployment.data_delete.mock_calls))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue