Files
python-heatclient/heatclient/tests/unit/osc/v1/test_software_deployment.py
shizhihui 5dbbc102eb Standardize import format
According to the rule in http://docs.openstack.org/developer/hacking/#imports
I modify some irregular import format in heatclinet.

Change-Id: I0200ddad88ee833d7de9d6df2c1519e4f4560db7
2016-08-03 19:45:05 +08:00

441 lines
17 KiB
Python

# 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 copy
import mock
from osc_lib import exceptions as exc
from heatclient import exc as heat_exc
from heatclient.osc.v1 import software_deployment
from heatclient.tests.unit.osc.v1 import fakes as orchestration_fakes
from heatclient.v1 import software_configs
from heatclient.v1 import software_deployments
class TestDeployment(orchestration_fakes.TestOrchestrationv1):
def setUp(self):
super(TestDeployment, self).setUp()
self.mock_client = self.app.client_manager.orchestration
self.config_client = self.mock_client.software_configs
self.sd_client = self.mock_client.software_deployments
class TestDeploymentCreate(TestDeployment):
server_id = '1234'
config_id = '5678'
deploy_id = '910'
config = {
'name': 'my_deploy',
'group': 'strict',
'config': '#!/bin/bash',
'inputs': [],
'outputs': [],
'options': [],
'id': config_id,
}
deployment = {
'server_id': server_id,
'input_values': {},
'action': 'UPDATE',
'status': 'IN_PROGRESS',
'status_reason': None,
'signal_id': 'signal_id',
'config_id': config_id,
'id': deploy_id,
}
config_defaults = {
'group': 'Heat::Ungrouped',
'config': '',
'options': {},
'inputs': [
{
'name': 'deploy_server_id',
'description': 'ID of the server being deployed to',
'type': 'String',
'value': server_id,
},
{
'name': 'deploy_action',
'description': 'Name of the current action being deployed',
'type': 'String',
'value': 'UPDATE',
},
{
'name': 'deploy_signal_transport',
'description': 'How the server should signal to heat with the '
'deployment output values.',
'type': 'String',
'value': 'TEMP_URL_SIGNAL',
},
{
'name': 'deploy_signal_id',
'description': 'ID of signal to use for signaling output '
'values',
'type': 'String',
'value': 'signal_id',
},
{
'name': 'deploy_signal_verb',
'description': 'HTTP verb to use for signaling output values',
'type': 'String',
'value': 'PUT',
},
],
'outputs': [],
'name': 'my_deploy',
}
deploy_defaults = {
'config_id': config_id,
'server_id': server_id,
'action': 'UPDATE',
'status': 'IN_PROGRESS',
}
def setUp(self):
super(TestDeploymentCreate, self).setUp()
self.cmd = software_deployment.CreateDeployment(self.app, None)
self.config_client.create.return_value = \
software_configs.SoftwareConfig(None, self.config)
self.config_client.get.return_value = \
software_configs.SoftwareConfig(None, self.config)
self.sd_client.create.return_value = \
software_deployments.SoftwareDeployment(None, self.deployment)
@mock.patch('heatclient.common.deployment_utils.build_signal_id',
return_value='signal_id')
def test_deployment_create(self, mock_build):
arglist = ['my_deploy', '--server', self.server_id]
expected_cols = ('action', 'config_id', 'id', 'input_values',
'server_id', 'signal_id', 'status', 'status_reason')
expected_data = ('UPDATE', self.config_id, self.deploy_id, {},
self.server_id, 'signal_id', 'IN_PROGRESS', None)
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.config_client.create.assert_called_with(**self.config_defaults)
self.sd_client.create.assert_called_with(
**self.deploy_defaults)
self.assertEqual(expected_cols, columns)
self.assertEqual(expected_data, data)
@mock.patch('heatclient.common.deployment_utils.build_signal_id',
return_value='signal_id')
def test_deployment_create_with_config(self, mock_build):
arglist = ['my_deploy', '--server', self.server_id,
'--config', self.config_id]
config = copy.deepcopy(self.config_defaults)
config['config'] = '#!/bin/bash'
config['group'] = 'strict'
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.config_client.get.assert_called_with(self.config_id)
self.config_client.create.assert_called_with(**config)
self.sd_client.create.assert_called_with(
**self.deploy_defaults)
def test_deployment_create_config_not_found(self):
arglist = ['my_deploy', '--server', self.server_id,
'--config', 'bad_id']
self.config_client.get.side_effect = heat_exc.HTTPNotFound
parsed_args = self.check_parser(self.cmd, arglist, [])
self.assertRaises(exc.CommandError, self.cmd.take_action, parsed_args)
def test_deployment_create_no_signal(self):
arglist = ['my_deploy', '--server', self.server_id,
'--signal-transport', 'NO_SIGNAL']
config = copy.deepcopy(self.config_defaults)
config['inputs'] = config['inputs'][:-2]
config['inputs'][2]['value'] = 'NO_SIGNAL'
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.config_client.create.assert_called_with(**config)
self.sd_client.create.assert_called_with(
**self.deploy_defaults)
@mock.patch('heatclient.common.deployment_utils.build_signal_id',
return_value='signal_id')
def test_deployment_create_invalid_signal_transport(self, mock_build):
arglist = ['my_deploy', '--server', self.server_id,
'--signal-transport', 'A']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.assertRaises(heat_exc.CommandError,
self.cmd.take_action, parsed_args)
@mock.patch('heatclient.common.deployment_utils.build_signal_id',
return_value='signal_id')
def test_deployment_create_input_value(self, mock_build):
arglist = ['my_deploy', '--server', self.server_id,
'--input-value', 'foo=bar']
config = copy.deepcopy(self.config_defaults)
config['inputs'].insert(
0, {'name': 'foo', 'type': 'String', 'value': 'bar'})
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.config_client.create.assert_called_with(**config)
self.sd_client.create.assert_called_with(
**self.deploy_defaults)
@mock.patch('heatclient.common.deployment_utils.build_signal_id',
return_value='signal_id')
def test_deployment_create_action(self, mock_build):
arglist = ['my_deploy', '--server', self.server_id,
'--action', 'DELETE']
config = copy.deepcopy(self.config_defaults)
config['inputs'][1]['value'] = 'DELETE'
deploy = copy.deepcopy(self.deploy_defaults)
deploy['action'] = 'DELETE'
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.config_client.create.assert_called_with(**config)
self.sd_client.create.assert_called_with(**deploy)
class TestDeploymentDelete(TestDeployment):
def setUp(self):
super(TestDeploymentDelete, self).setUp()
self.cmd = software_deployment.DeleteDeployment(self.app, None)
def test_deployment_delete_success(self):
arglist = ['test_deployment']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.sd_client.delete.assert_called_with(
deployment_id='test_deployment')
def test_deployment_delete_multiple(self):
arglist = ['test_deployment', 'test_deployment2']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.sd_client.delete.assert_has_calls(
[mock.call(deployment_id='test_deployment'),
mock.call(deployment_id='test_deployment2')])
def test_deployment_delete_not_found(self):
arglist = ['test_deployment', 'test_deployment2']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.delete.side_effect = heat_exc.HTTPNotFound()
error = self.assertRaises(
exc.CommandError, self.cmd.take_action, parsed_args)
self.assertIn("Unable to delete 2 of the 2 deployments.", str(error))
def test_deployment_config_delete_failed(self):
arglist = ['test_deployment']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.config_client.delete.side_effect = heat_exc.HTTPNotFound()
self.assertIsNone(self.cmd.take_action(parsed_args))
class TestDeploymentList(TestDeployment):
columns = ['id', 'config_id', 'server_id', 'action', 'status']
data = {"software_deployments": [
{
"status": "COMPLETE",
"server_id": "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5",
"config_id": "8da95794-2ad9-4979-8ae5-739ce314c5cd",
"output_values": {
"deploy_stdout": "Writing to /tmp/barmy Written to /tmp/barmy",
"deploy_stderr": "+ echo Writing to /tmp/barmy\n+ echo fu\n+ c"
"at /tmp/barmy\n+ echo -n The file /tmp/barmy"
"contains for server ec14c864-096e-4e27-bb8a-"
"2c2b4dc6f3f5 during CREATE\n+"
"echo Output to stderr\nOutput to stderr\n",
"deploy_status_code": 0,
"result": "The file /tmp/barmy contains fu for server "
"ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5 during CREATE"
},
"input_values": None,
"action": "CREATE",
"status_reason": "Outputs received",
"id": "ef422fa5-719a-419e-a10c-72e3a367b0b8",
"creation_time": "2015-01-31T15:12:36Z",
"updated_time": "2015-01-31T15:18:21Z"
}
]
}
def setUp(self):
super(TestDeploymentList, self).setUp()
self.cmd = software_deployment.ListDeployment(self.app, None)
self.sd_client.list = mock.MagicMock(return_value=[self.data])
def test_deployment_list(self):
arglist = []
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.sd_client.list.assert_called_with()
self.assertEqual(self.columns, columns)
def test_deployment_list_server(self):
kwargs = {}
kwargs['server_id'] = 'ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5'
arglist = ['--server', 'ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5']
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.sd_client.list.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
def test_deployment_list_long(self):
kwargs = {}
cols = ['id', 'config_id', 'server_id', 'action', 'status',
'creation_time', 'status_reason']
arglist = ['--long']
parsed_args = self.check_parser(self.cmd, arglist, [])
columns, data = self.cmd.take_action(parsed_args)
self.sd_client.list.assert_called_with(**kwargs)
self.assertEqual(cols, columns)
class TestDeploymentShow(TestDeployment):
get_response = {"software_deployment": {
"status": "IN_PROGRESS",
"server_id": "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5",
"config_id": "3d5ec2a8-7004-43b6-a7f6-542bdbe9d434",
"output_values": 'null',
"input_values": 'null',
"action": "CREATE",
"status_reason": "Deploy data available",
"id": "06e87bcc-33a2-4bce-aebd-533e698282d3",
"creation_time": "2015-01-31T15:12:36Z",
"updated_time": "2015-01-31T15:18:21Z"
}}
def setUp(self):
super(TestDeploymentShow, self).setUp()
self.cmd = software_deployment.ShowDeployment(self.app, None)
def test_deployment_show(self):
arglist = ['my_deployment']
cols = ['id', 'server_id', 'config_id', 'creation_time',
'updated_time', 'status', 'status_reason',
'input_values', 'action']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.get.return_value = \
software_deployments.SoftwareDeployment(
None, self.get_response)
columns, data = self.cmd.take_action(parsed_args)
self.sd_client.get.assert_called_with(**{
'deployment_id': 'my_deployment',
})
self.assertEqual(cols, columns)
def test_deployment_show_long(self):
arglist = ['my_deployment', '--long']
cols = ['id', 'server_id', 'config_id', 'creation_time',
'updated_time', 'status', 'status_reason',
'input_values', 'action', 'output_values']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.get.return_value = \
software_deployments.SoftwareDeployment(
None, self.get_response)
columns, data = self.cmd.take_action(parsed_args)
self.sd_client.get.assert_called_once_with(**{
'deployment_id': 'my_deployment',
})
self.assertEqual(cols, columns)
def test_deployment_not_found(self):
arglist = ['my_deployment']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.get.side_effect = heat_exc.HTTPNotFound()
self.assertRaises(
exc.CommandError,
self.cmd.take_action,
parsed_args)
class TestDeploymentMetadataShow(TestDeployment):
def setUp(self):
super(TestDeploymentMetadataShow, self).setUp()
self.cmd = software_deployment.ShowMetadataDeployment(self.app, None)
self.sd_client.metadata.return_value = {}
def test_deployment_show_metadata(self):
arglist = ['ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.cmd.take_action(parsed_args)
self.sd_client.metadata.assert_called_with(
server_id='ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5')
class TestDeploymentOutputShow(TestDeployment):
get_response = {
"status": "IN_PROGRESS",
"server_id": "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5",
"config_id": "3d5ec2a8-7004-43b6-a7f6-542bdbe9d434",
"output_values": None,
"input_values": None,
"action": "CREATE",
"status_reason": "Deploy data available",
"id": "06e87bcc-33a2-4bce-aebd-533e698282d3",
"creation_time": "2015-01-31T15:12:36Z",
"updated_time": "2015-01-31T15:18:21Z"
}
def setUp(self):
super(TestDeploymentOutputShow, self).setUp()
self.cmd = software_deployment.ShowOutputDeployment(self.app, None)
def test_deployment_output_show(self):
arglist = ['85c3a507-351b-4b28-a7d8-531c8d53f4e6', '--all', '--long']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.get.return_value = \
software_deployments.SoftwareDeployment(
None, self.get_response)
self.cmd.take_action(parsed_args)
self.sd_client.get.assert_called_with(**{
'deployment_id': '85c3a507-351b-4b28-a7d8-531c8d53f4e6'
})
def test_deployment_output_show_invalid(self):
arglist = ['85c3a507-351b-4b28-a7d8-531c8d53f4e6']
parsed_args = self.check_parser(self.cmd, arglist, [])
error = self.assertRaises(
exc.CommandError,
self.cmd.take_action,
parsed_args)
self.assertIn('either <output-name> or --all argument is needed',
str(error))
def test_deployment_output_show_not_found(self):
arglist = ['85c3a507-351b-4b28-a7d8-531c8d53f4e6', '--all']
parsed_args = self.check_parser(self.cmd, arglist, [])
self.sd_client.get.side_effect = heat_exc.HTTPNotFound()
self.assertRaises(
exc.CommandError,
self.cmd.take_action,
parsed_args)