summaryrefslogtreecommitdiff
path: root/heatclient/tests
diff options
context:
space:
mode:
Diffstat (limited to 'heatclient/tests')
-rw-r--r--heatclient/tests/functional/osc/v1/base.py4
-rw-r--r--heatclient/tests/unit/osc/v1/test_event.py12
-rw-r--r--heatclient/tests/unit/osc/v1/test_snapshot.py28
-rw-r--r--heatclient/tests/unit/osc/v1/test_stack.py76
-rw-r--r--heatclient/tests/unit/osc/v1/test_template.py29
-rw-r--r--heatclient/tests/unit/test_common_http.py679
-rw-r--r--heatclient/tests/unit/test_event_utils.py112
-rw-r--r--heatclient/tests/unit/test_events.py124
-rw-r--r--heatclient/tests/unit/test_resources.py12
-rw-r--r--heatclient/tests/unit/test_shell.py159
-rw-r--r--heatclient/tests/unit/test_template_utils.py508
11 files changed, 940 insertions, 803 deletions
diff --git a/heatclient/tests/functional/osc/v1/base.py b/heatclient/tests/functional/osc/v1/base.py
index 31a9cd7..b17fb4c 100644
--- a/heatclient/tests/functional/osc/v1/base.py
+++ b/heatclient/tests/functional/osc/v1/base.py
@@ -48,7 +48,7 @@ class OpenStackClientTestBase(base.ClientTestBase):
items = self.parser.listing(output)
for item in items:
obj[item['Field']] = six.text_type(item['Value'])
- return dict((self._key_name(k), v) for k, v in six.iteritems(obj))
+ return dict((self._key_name(k), v) for k, v in obj.items())
def _key_name(self, key):
return key.lower().replace(' ', '_')
@@ -60,7 +60,7 @@ class OpenStackClientTestBase(base.ClientTestBase):
if item['ID'] == id:
obj = item
break
- return dict((self._key_name(k), v) for k, v in six.iteritems(obj))
+ return dict((self._key_name(k), v) for k, v in obj.items())
def _stack_create(self, name, template, parameters=[], wait=True):
cmd = 'stack create ' + name
diff --git a/heatclient/tests/unit/osc/v1/test_event.py b/heatclient/tests/unit/osc/v1/test_event.py
index 3c64b92..d7ecb60 100644
--- a/heatclient/tests/unit/osc/v1/test_event.py
+++ b/heatclient/tests/unit/osc/v1/test_event.py
@@ -194,7 +194,9 @@ class TestEventList(TestEvent):
mock_sort_items.assert_called_with(mock.ANY,
"resource_name:desc")
- self.event_client.list.assert_called_with(**self.defaults)
+ self.event_client.list.assert_called_with(
+ filters={}, resource_name=None, sort_dir='desc',
+ sort_keys=['resource_name'], stack_id='my_stack')
self.assertEqual(self.fields, columns)
@mock.patch('osc_lib.utils.sort_items')
@@ -209,7 +211,9 @@ class TestEventList(TestEvent):
mock_sort_items.assert_called_with(mock.ANY,
"resource_name:desc,id:asc")
- self.event_client.list.assert_called_with(**self.defaults)
+ self.event_client.list.assert_called_with(
+ filters={}, resource_name=None, sort_dir='desc',
+ sort_keys=['resource_name', 'id'], stack_id='my_stack')
self.assertEqual(self.fields, columns)
@mock.patch('osc_lib.utils.sort_items')
@@ -223,7 +227,9 @@ class TestEventList(TestEvent):
columns, data = self.cmd.take_action(parsed_args)
mock_sort_items.assert_called_with(mock.ANY, "event_time:desc")
- self.event_client.list.assert_called_with(**self.defaults)
+ self.event_client.list.assert_called_with(
+ filters={}, resource_name=None, sort_dir='desc', sort_keys=[],
+ stack_id='my_stack')
self.assertEqual(self.fields, columns)
@mock.patch('time.sleep')
diff --git a/heatclient/tests/unit/osc/v1/test_snapshot.py b/heatclient/tests/unit/osc/v1/test_snapshot.py
index f51a6ed..7f69c61 100644
--- a/heatclient/tests/unit/osc/v1/test_snapshot.py
+++ b/heatclient/tests/unit/osc/v1/test_snapshot.py
@@ -10,8 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
#
-
+import mock
from osc_lib import exceptions as exc
+import six
from heatclient import exc as heat_exc
from heatclient.osc.v1 import snapshot
@@ -157,3 +158,28 @@ class TestSnapshotDelete(TestStack):
exc.CommandError,
self.cmd.take_action,
parsed_args)
+
+ @mock.patch('sys.stdin', spec=six.StringIO)
+ def test_snapshot_delete_prompt(self, mock_stdin):
+ arglist = ['my_stack', 'snapshot_id']
+ mock_stdin.isatty.return_value = True
+ mock_stdin.readline.return_value = 'y'
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ self.cmd.take_action(parsed_args)
+
+ mock_stdin.readline.assert_called_with()
+ self.stack_client.snapshot_delete.assert_called_with('my_stack',
+ 'snapshot_id')
+
+ @mock.patch('sys.stdin', spec=six.StringIO)
+ def test_snapshot_delete_prompt_no(self, mock_stdin):
+ arglist = ['my_stack', 'snapshot_id']
+ mock_stdin.isatty.return_value = True
+ mock_stdin.readline.return_value = 'n'
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ self.cmd.take_action(parsed_args)
+
+ mock_stdin.readline.assert_called_with()
+ self.stack_client.snapshot_delete.assert_not_called()
diff --git a/heatclient/tests/unit/osc/v1/test_stack.py b/heatclient/tests/unit/osc/v1/test_stack.py
index c40bdf1..54fe9be 100644
--- a/heatclient/tests/unit/osc/v1/test_stack.py
+++ b/heatclient/tests/unit/osc/v1/test_stack.py
@@ -149,7 +149,8 @@ class TestStackCreate(TestStack):
self.cmd.take_action(parsed_args)
self.stack_client.create.assert_called_with(**self.defaults)
- self.stack_client.get.assert_called_with(**{'stack_id': '1234'})
+ self.stack_client.get.assert_called_with(**{'stack_id': '1234',
+ 'resolve_outputs': False})
@mock.patch('heatclient.common.event_utils.poll_for_events',
return_value=('CREATE_FAILED',
@@ -347,7 +348,8 @@ class TestStackUpdate(TestStack):
self.cmd.take_action(parsed_args)
self.stack_client.update.assert_called_with(**self.defaults)
- self.stack_client.get.assert_called_with(**{'stack_id': 'my_stack'})
+ self.stack_client.get.assert_called_with(**{'stack_id': 'my_stack',
+ 'resolve_outputs': False})
@mock.patch('heatclient.common.event_utils.poll_for_events',
return_value=('UPDATE_FAILED',
@@ -414,6 +416,16 @@ class TestStackShow(TestStack):
self.cmd.take_action(parsed_args)
self.stack_client.get.assert_called_with(**{
'stack_id': 'my_stack',
+ 'resolve_outputs': True,
+ })
+
+ def test_stack_show_explicit_no_resolve(self):
+ arglist = ['--no-resolve-outputs', '--format', self.format, 'my_stack']
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+ self.cmd.take_action(parsed_args)
+ self.stack_client.get.assert_called_with(**{
+ 'stack_id': 'my_stack',
+ 'resolve_outputs': False,
})
def test_stack_show_short(self):
@@ -453,6 +465,9 @@ class TestStackList(TestStack):
'deletion_time': '2015-10-21T07:50:00Z',
}
+ data_with_project = copy.deepcopy(data)
+ data_with_project['project'] = 'test_project'
+
def setUp(self):
super(TestStackList, self).setUp()
self.cmd = stack.ListStack(self.app, None)
@@ -495,6 +510,8 @@ class TestStackList(TestStack):
self.assertEqual(cols, columns)
def test_stack_list_all_projects(self):
+ self.stack_client.list.return_value = [
+ stacks.Stack(None, self.data_with_project)]
kwargs = copy.deepcopy(self.defaults)
kwargs['global_tenant'] = True
cols = copy.deepcopy(self.columns)
@@ -507,7 +524,23 @@ class TestStackList(TestStack):
self.stack_client.list.assert_called_with(**kwargs)
self.assertEqual(cols, columns)
+ def test_stack_list_with_project(self):
+ self.stack_client.list.return_value = [
+ stacks.Stack(None, self.data_with_project)]
+ kwargs = copy.deepcopy(self.defaults)
+ cols = copy.deepcopy(self.columns)
+ cols.insert(2, 'Project')
+ arglist = []
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.stack_client.list.assert_called_with(**kwargs)
+ self.assertEqual(cols, columns)
+
def test_stack_list_long(self):
+ self.stack_client.list.return_value = [
+ stacks.Stack(None, self.data_with_project)]
kwargs = copy.deepcopy(self.defaults)
kwargs['global_tenant'] = True
cols = copy.deepcopy(self.columns)
@@ -729,7 +762,8 @@ class TestStackAdopt(TestStack):
self.cmd.take_action(parsed_args)
self.stack_client.create.assert_called_with(**self.defaults)
- self.stack_client.get.assert_called_with(**{'stack_id': '1234'})
+ self.stack_client.get.assert_called_with(**{'stack_id': '1234',
+ 'resolve_outputs': False})
@mock.patch('heatclient.common.event_utils.poll_for_events',
return_value=('ADOPT_FAILED',
@@ -743,6 +777,42 @@ class TestStackAdopt(TestStack):
self.assertRaises(exc.CommandError, self.cmd.take_action, parsed_args)
+class TestStackExport(TestStack):
+
+ columns = ['stack_name', 'stack_status', 'id']
+ data = ['my_stack', 'ABANDONED', '1234']
+
+ response = dict(zip(columns, data))
+
+ def setUp(self):
+ super(TestStackExport, self).setUp()
+ self.cmd = stack.ExportStack(self.app, None)
+ self.stack_client.export.return_value = self.response
+
+ def test_stack_export(self):
+ arglist = ['my_stack']
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ for column in self.columns:
+ self.assertIn(column, columns)
+ for datum in self.data:
+ self.assertIn(datum, data)
+
+ @mock.patch('heatclient.osc.v1.stack.open', create=True)
+ def test_stack_export_output_file(self, mock_open):
+ arglist = ['my_stack', '--output-file', 'file.json']
+ mock_open.return_value = mock.MagicMock(spec=io.IOBase)
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ mock_open.assert_called_once_with('file.json', 'w')
+ self.assertEqual([], columns)
+ self.assertIsNone(data)
+
+
class TestStackAbandon(TestStack):
columns = ['stack_name', 'stack_status', 'id']
diff --git a/heatclient/tests/unit/osc/v1/test_template.py b/heatclient/tests/unit/osc/v1/test_template.py
index c9b67ca..3a85c99 100644
--- a/heatclient/tests/unit/osc/v1/test_template.py
+++ b/heatclient/tests/unit/osc/v1/test_template.py
@@ -29,19 +29,17 @@ class TestTemplate(fakes.TestOrchestrationv1):
class TestTemplateVersionList(TestTemplate):
- defaults = [
- {'version': 'HOT123', 'type': 'hot'},
- {'version': 'CFN456', 'type': 'cfn'}
- ]
-
- def setUp(self):
- super(TestTemplateVersionList, self).setUp()
- tv1 = template_versions.TemplateVersion(None, self.defaults[0])
- tv2 = template_versions.TemplateVersion(None, self.defaults[1])
+ def _stub_versions_list(self, ret_data):
+ tv1 = template_versions.TemplateVersion(None, ret_data[0])
+ tv2 = template_versions.TemplateVersion(None, ret_data[1])
self.template_versions.list.return_value = [tv1, tv2]
self.cmd = template.VersionList(self.app, None)
def test_version_list(self):
+ ret_data = [
+ {'version': 'HOT123', 'type': 'hot'},
+ {'version': 'CFN456', 'type': 'cfn'}]
+ self._stub_versions_list(ret_data)
parsed_args = self.check_parser(self.cmd, [], [])
columns, data = self.cmd.take_action(parsed_args)
@@ -49,6 +47,19 @@ class TestTemplateVersionList(TestTemplate):
self.assertEqual(['Version', 'Type'], columns)
self.assertEqual([('HOT123', 'hot'), ('CFN456', 'cfn')], list(data))
+ def test_version_list_with_aliases(self):
+ ret_data = [
+ {'version': 'HOT123', 'type': 'hot', 'aliases': ['releasex']},
+ {'version': 'CFN456', 'type': 'cfn', 'aliases': ['releasey']}]
+ self._stub_versions_list(ret_data)
+ parsed_args = self.check_parser(self.cmd, [], [])
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.assertEqual(['Version', 'Type', 'Aliases'], columns)
+ self.assertEqual([('HOT123', 'hot', 'releasex'),
+ ('CFN456', 'cfn', 'releasey')], list(data))
+
class TestTemplateFunctionList(TestTemplate):
diff --git a/heatclient/tests/unit/test_common_http.py b/heatclient/tests/unit/test_common_http.py
index 9ccc24a..8ce6f18 100644
--- a/heatclient/tests/unit/test_common_http.py
+++ b/heatclient/tests/unit/test_common_http.py
@@ -12,15 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import logging
-import os
import socket
from keystoneauth1 import adapter
import mock
-import mox
from oslo_serialization import jsonutils
-import requests
import six
import testtools
@@ -30,138 +26,108 @@ from heatclient import exc
from heatclient.tests.unit import fakes
+@mock.patch('heatclient.common.http.requests.request')
class HttpClientTest(testtools.TestCase):
- # Patch os.environ to avoid required auth info.
- def setUp(self):
- super(HttpClientTest, self).setUp()
- self.m = mox.Mox()
- self.m.StubOutWithMock(requests, 'request')
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
- def test_http_raw_request(self):
+ def test_http_raw_request(self, mock_request):
headers = {'Content-Type': 'application/octet-stream',
'User-Agent': 'python-heatclient'}
# Record a 200
- mock_conn = http.requests.request('GET', 'http://example.com:8004',
- allow_redirects=False,
- headers=headers)
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/octet-stream'},
- ''))
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/octet-stream'},
+ '')
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
self.assertEqual('', ''.join([x for x in resp.content]))
+ mock_request.assert_called_with('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers=headers)
- def test_token_or_credentials(self):
+ def test_token_or_credentials(self, mock_request):
# Record a 200
fake200 = fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/octet-stream'},
'')
+ mock_request.return_value = fake200
# no token or credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(fake200)
-
- # credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient',
- 'X-Auth-Key': 'pass',
- 'X-Auth-User': 'user'})
- mock_conn.AndReturn(fake200)
-
- # token suppresses credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient',
- 'X-Auth-Token': 'abcd1234'})
- mock_conn.AndReturn(fake200)
-
- # Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
+ # credentials
client.username = 'user'
client.password = 'pass'
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
+ # token suppresses credentials
client.auth_token = 'abcd1234'
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
- def test_include_pass(self):
+ mock_request.assert_has_calls([
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient',
+ 'X-Auth-Key': 'pass',
+ 'X-Auth-User': 'user'}),
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient',
+ 'X-Auth-Token': 'abcd1234'})
+ ])
+
+ def test_include_pass(self, mock_request):
# Record a 200
fake200 = fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/octet-stream'},
'')
-
+ mock_request.return_value = fake200
# no token or credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(fake200)
-
- # credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient',
- 'X-Auth-Key': 'pass',
- 'X-Auth-User': 'user'})
- mock_conn.AndReturn(fake200)
-
- # token suppresses credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient',
- 'X-Auth-Token': 'abcd1234',
- 'X-Auth-Key': 'pass',
- 'X-Auth-User': 'user'})
- mock_conn.AndReturn(fake200)
-
- # Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
+ # credentials
client.username = 'user'
client.password = 'pass'
client.include_pass = True
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
+ # token suppresses credentials
client.auth_token = 'abcd1234'
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
- def test_not_include_pass(self):
+ mock_request.assert_has_calls([
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient',
+ 'X-Auth-Key': 'pass',
+ 'X-Auth-User': 'user'}),
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient',
+ 'X-Auth-Token': 'abcd1234',
+ 'X-Auth-Key': 'pass',
+ 'X-Auth-User': 'user'})
+ ])
+
+ def test_not_include_pass(self, mock_request):
# Record a 200
fake500 = fakes.FakeHTTPResponse(
500, 'ERROR',
@@ -169,21 +135,20 @@ class HttpClientTest(testtools.TestCase):
'(HTTP 401)')
# no token or credentials
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(fake500)
+ mock_request.return_value = fake500
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
e = self.assertRaises(exc.HTTPUnauthorized,
client.raw_request, 'GET', '')
self.assertIn('Authentication failed', str(e))
+ mock_request.assert_called_with(
+ 'GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/octet-stream',
+ 'User-Agent': 'python-heatclient'})
- def test_region_name(self):
+ def test_region_name(self, mock_request):
# Record a 200
fake200 = fakes.FakeHTTPResponse(
200, 'OK',
@@ -191,61 +156,46 @@ class HttpClientTest(testtools.TestCase):
'')
# Specify region name
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/octet-stream',
- 'X-Region-Name': 'RegionOne',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(fake200)
+ mock_request.return_value = fake200
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
client.region_name = 'RegionOne'
resp = client.raw_request('GET', '')
self.assertEqual(200, resp.status_code)
-
- def test_http_json_request(self):
- # Record a 200
- mock_conn = http.requests.request(
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
+ headers={'Content-Type': 'application/octet-stream',
+ 'X-Region-Name': 'RegionOne',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/json'},
- '{}'))
+
+ def test_http_json_request(self, mock_request):
+ # Record a 200
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/json'},
+ '{}')
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp, body = client.json_request('GET', '')
self.assertEqual(200, resp.status_code)
self.assertEqual({}, body)
-
- def test_http_json_request_argument_passed_to_requests(self):
- """Check that we have sent the proper arguments to requests."""
- # Record a 200
- mock_conn = http.requests.request(
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
allow_redirects=False,
- cert=('RANDOM_CERT_FILE', 'RANDOM_KEY_FILE'),
- verify=True,
- data='"text"',
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
- 'X-Auth-Url': 'http://AUTH_URL',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/json'},
- '{}'))
- # Replay, create client, assert
- self.m.ReplayAll()
+
+ def test_http_json_request_argument_passed_to_requests(self, mock_request):
+ """Check that we have sent the proper arguments to requests."""
+ # Record a 200
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/json'},
+ '{}')
+
client = http.HTTPClient('http://example.com:8004')
client.verify_cert = True
client.cert_file = 'RANDOM_CERT_FILE'
@@ -254,395 +204,360 @@ class HttpClientTest(testtools.TestCase):
resp, body = client.json_request('GET', '', data='text')
self.assertEqual(200, resp.status_code)
self.assertEqual({}, body)
-
- def test_http_json_request_w_req_body(self):
- # Record a 200
- mock_conn = http.requests.request(
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
- body='test-body',
allow_redirects=False,
+ cert=('RANDOM_CERT_FILE', 'RANDOM_KEY_FILE'),
+ verify=True,
+ data='"text"',
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
+ 'X-Auth-Url': 'http://AUTH_URL',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/json'},
- '{}'))
+
+ def test_http_json_request_w_req_body(self, mock_request):
+ # Record a 200
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/json'},
+ '{}')
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp, body = client.json_request('GET', '', body='test-body')
self.assertEqual(200, resp.status_code)
- self.assertEqual({}, body)
-
- def test_http_json_request_non_json_resp_cont_type(self):
- # Record a 200
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004', body='test-body',
+ mock_request.assert_called_with(
+ 'GET', 'http://example.com:8004',
+ body='test-body',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'not/json'},
- {}))
+
+ def test_http_json_request_non_json_resp_cont_type(self, mock_request):
+ # Record a 200i
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'not/json'},
+ '{}')
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp, body = client.json_request('GET', '', body='test-body')
self.assertEqual(200, resp.status_code)
self.assertIsNone(body)
-
- def test_http_json_request_invalid_json(self):
- # Record a 200
- mock_conn = http.requests.request(
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
+ body='test-body',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/json'},
- 'invalid-json'))
+
+ def test_http_json_request_invalid_json(self, mock_request):
+ # Record a 200
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/json'},
+ 'invalid-json')
+
# Replay, create client, assert
- self.m.ReplayAll()
client = http.HTTPClient('http://example.com:8004')
resp, body = client.json_request('GET', '')
self.assertEqual(200, resp.status_code)
self.assertEqual('invalid-json', body)
-
- def test_http_manual_redirect_delete(self):
- mock_conn = http.requests.request(
- 'DELETE', 'http://example.com:8004/foo',
+ mock_request.assert_called_with(
+ 'GET', 'http://example.com:8004',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+
+ def test_http_manual_redirect_delete(self, mock_request):
+ mock_request.side_effect = [
fakes.FakeHTTPResponse(
302, 'Found',
{'location': 'http://example.com:8004/foo/bar'},
- ''))
- mock_conn = http.requests.request(
- 'DELETE', 'http://example.com:8004/foo/bar',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ ''),
fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/json'},
- '{}'))
-
- self.m.ReplayAll()
+ 'invalid-json')
+ ]
client = http.HTTPClient('http://example.com:8004/foo')
resp, body = client.json_request('DELETE', '')
- self.assertEqual(200, resp.status_code)
-
- def test_http_manual_redirect_post(self):
- mock_conn = http.requests.request(
- 'POST', 'http://example.com:8004/foo',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ mock_request.assert_has_calls([
+ mock.call('DELETE', 'http://example.com:8004/foo',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('DELETE', 'http://example.com:8004/foo/bar',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
+ ])
+
+ def test_http_manual_redirect_post(self, mock_request):
+ mock_request.side_effect = [
fakes.FakeHTTPResponse(
302, 'Found',
{'location': 'http://example.com:8004/foo/bar'},
- ''))
- mock_conn = http.requests.request(
- 'POST', 'http://example.com:8004/foo/bar',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ ''),
fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/json'},
- '{}'))
-
- self.m.ReplayAll()
+ 'invalid-json')
+ ]
client = http.HTTPClient('http://example.com:8004/foo')
resp, body = client.json_request('POST', '')
- self.assertEqual(200, resp.status_code)
-
- def test_http_manual_redirect_put(self):
- mock_conn = http.requests.request(
- 'PUT', 'http://example.com:8004/foo',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ mock_request.assert_has_calls([
+ mock.call('POST', 'http://example.com:8004/foo',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('POST', 'http://example.com:8004/foo/bar',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
+ ])
+
+ def test_http_manual_redirect_put(self, mock_request):
+ mock_request.side_effect = [
fakes.FakeHTTPResponse(
302, 'Found',
{'location': 'http://example.com:8004/foo/bar'},
- ''))
- mock_conn = http.requests.request(
- 'PUT', 'http://example.com:8004/foo/bar',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ ''),
fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/json'},
- '{}'))
-
- self.m.ReplayAll()
+ 'invalid-json')
+ ]
client = http.HTTPClient('http://example.com:8004/foo')
resp, body = client.json_request('PUT', '')
- self.assertEqual(200, resp.status_code)
-
- def test_http_manual_redirect_put_uppercase(self):
- mock_conn = http.requests.request(
- 'PUT', 'http://EXAMPLE.com:8004/foo',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ mock_request.assert_has_calls([
+ mock.call('PUT', 'http://example.com:8004/foo',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('PUT', 'http://example.com:8004/foo/bar',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
+ ])
+
+ def test_http_manual_redirect_put_uppercase(self, mock_request):
+ mock_request.side_effect = [
fakes.FakeHTTPResponse(
302, 'Found',
{'location': 'http://example.com:8004/foo/bar'},
- ''))
- mock_conn = http.requests.request(
- 'PUT', 'http://example.com:8004/foo/bar',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ ''),
fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/json'},
- '{}'))
-
- self.m.ReplayAll()
-
+ 'invalid-json')
+ ]
client = http.HTTPClient('http://EXAMPLE.com:8004/foo')
resp, body = client.json_request('PUT', '')
-
self.assertEqual(200, resp.status_code)
- def test_http_manual_redirect_error_without_location(self):
- mock_conn = http.requests.request(
- 'DELETE', 'http://example.com:8004/foo',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 302, 'Found',
- {},
- ''))
- self.m.ReplayAll()
+ mock_request.assert_has_calls([
+ mock.call('PUT', 'http://EXAMPLE.com:8004/foo',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('PUT', 'http://example.com:8004/foo/bar',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
+ ])
+
+ def test_http_manual_redirect_error_without_location(self, mock_request):
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 302, 'Found',
+ {},
+ '')
client = http.HTTPClient('http://example.com:8004/foo')
self.assertRaises(exc.InvalidEndpoint,
client.json_request, 'DELETE', '')
-
- def test_http_json_request_redirect(self):
- # Record the 302
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
+ mock_request.assert_called_once_with(
+ 'DELETE', 'http://example.com:8004/foo',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+
+ def test_http_json_request_redirect(self, mock_request):
+ # Record the 302
+ mock_request.side_effect = [
fakes.FakeHTTPResponse(
302, 'Found',
{'location': 'http://example.com:8004'},
- ''))
- # Record the following 200
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
+ ''),
fakes.FakeHTTPResponse(
200, 'OK',
{'content-type': 'application/json'},
- '{}'))
- # Replay, create client, assert
- self.m.ReplayAll()
+ '{}')
+ ]
client = http.HTTPClient('http://example.com:8004')
resp, body = client.json_request('GET', '')
self.assertEqual(200, resp.status_code)
self.assertEqual({}, body)
-
- def test_http_404_json_request(self):
+ mock_request.assert_has_calls([
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'}),
+ mock.call('GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
+ ])
+
+ def test_http_404_json_request(self, mock_request):
# Record a 404
- mock_conn = http.requests.request(
- 'GET', 'http://example.com:8004',
- allow_redirects=False,
- headers={'Content-Type': 'application/json',
- 'Accept': 'application/json',
- 'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 404, 'OK', {'content-type': 'application/json'},
- '{}'))
- # Replay, create client, assert
- self.m.ReplayAll()
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 404, 'OK', {'content-type': 'application/json'},
+ '{}')
client = http.HTTPClient('http://example.com:8004')
e = self.assertRaises(exc.HTTPNotFound, client.json_request, 'GET', '')
# Assert that the raised exception can be converted to string
self.assertIsNotNone(str(e))
-
- def test_http_300_json_request(self):
- # Record a 300
- mock_conn = http.requests.request(
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'})
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 300, 'OK', {'content-type': 'application/json'},
- '{}'))
- # Replay, create client, assert
- self.m.ReplayAll()
+
+ def test_http_300_json_request(self, mock_request):
+ # Record a 300
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 300, 'OK', {'content-type': 'application/json'},
+ '{}')
+ # Assert that the raised exception can be converted to string
client = http.HTTPClient('http://example.com:8004')
e = self.assertRaises(
exc.HTTPMultipleChoices, client.json_request, 'GET', '')
- # Assert that the raised exception can be converted to string
self.assertIsNotNone(str(e))
+ mock_request.assert_called_with(
+ 'GET', 'http://example.com:8004',
+ allow_redirects=False,
+ headers={'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ 'User-Agent': 'python-heatclient'})
- def test_fake_json_request(self):
+ def test_fake_json_request(self, mock_request):
headers = {'User-Agent': 'python-heatclient'}
- mock_conn = http.requests.request('GET', 'fake://example.com:8004/',
- allow_redirects=False,
- headers=headers)
- mock_conn.AndRaise(socket.gaierror)
- self.m.ReplayAll()
-
+ mock_request.side_effect = [socket.gaierror]
client = http.HTTPClient('fake://example.com:8004')
self.assertRaises(exc.InvalidEndpoint,
client._http_request, "/", "GET")
- def test_debug_curl_command(self):
- self.m.StubOutWithMock(logging.Logger, 'debug')
-
- ssl_connection_params = {'ca_file': 'TEST_CA',
- 'cert_file': 'TEST_CERT',
- 'key_file': 'TEST_KEY',
- 'insecure': 'TEST_NSA'}
-
- headers = {'key': 'value'}
-
- mock_logging_debug = logging.Logger.debug(
- "curl -g -i -X GET -H 'key: value' --key TEST_KEY "
- "--cert TEST_CERT --cacert TEST_CA "
- "-k -d 'text' http://foo/bar"
- )
- mock_logging_debug.AndReturn(None)
- self.m.ReplayAll()
-
- client = http.HTTPClient('http://foo')
- client.ssl_connection_params = ssl_connection_params
- client.log_curl_request('GET', '/bar', {'headers': headers,
- 'data': 'text'})
-
- def test_http_request_socket_error(self):
+ mock_request.assert_called_with('GET', 'fake://example.com:8004/',
+ allow_redirects=False,
+ headers=headers)
+
+ def test_debug_curl_command(self, mock_request):
+ with mock.patch('logging.Logger.debug') as mock_logging_debug:
+
+ ssl_connection_params = {'ca_file': 'TEST_CA',
+ 'cert_file': 'TEST_CERT',
+ 'key_file': 'TEST_KEY',
+ 'insecure': 'TEST_NSA'}
+
+ headers = {'key': 'value'}
+ mock_logging_debug.return_value = None
+ client = http.HTTPClient('http://foo')
+ client.ssl_connection_params = ssl_connection_params
+ client.log_curl_request('GET', '/bar', {'headers': headers,
+ 'data': 'text'})
+ mock_logging_debug.assert_called_with(
+ "curl -g -i -X GET -H 'key: value' --key TEST_KEY "
+ "--cert TEST_CERT --cacert TEST_CA "
+ "-k -d 'text' http://foo/bar"
+ )
+
+ def test_http_request_socket_error(self, mock_request):
headers = {'User-Agent': 'python-heatclient'}
- mock_conn = http.requests.request('GET', 'http://example.com:8004/',
- allow_redirects=False,
- headers=headers)
- mock_conn.AndRaise(socket.error)
- self.m.ReplayAll()
+ mock_request.side_effect = [socket.error]
client = http.HTTPClient('http://example.com:8004')
self.assertRaises(exc.CommunicationError,
client._http_request, "/", "GET")
+ mock_request.assert_called_with('GET', 'http://example.com:8004/',
+ allow_redirects=False,
+ headers=headers)
- def test_http_request_socket_timeout(self):
+ def test_http_request_socket_timeout(self, mock_request):
headers = {'User-Agent': 'python-heatclient'}
- mock_conn = http.requests.request('GET', 'http://example.com:8004/',
- allow_redirects=False,
- headers=headers)
- mock_conn.AndRaise(socket.timeout)
- self.m.ReplayAll()
+ mock_request.side_effect = [socket.timeout]
client = http.HTTPClient('http://example.com:8004')
self.assertRaises(exc.CommunicationError,
client._http_request, "/", "GET")
+ mock_request.assert_called_with('GET', 'http://example.com:8004/',
+ allow_redirects=False,
+ headers=headers)
- def test_http_request_specify_timeout(self):
- mock_conn = http.requests.request(
+ def test_http_request_specify_timeout(self, mock_request):
+ mock_request.return_value = fakes.FakeHTTPResponse(
+ 200, 'OK',
+ {'content-type': 'application/json'},
+ '{}')
+ client = http.HTTPClient('http://example.com:8004', timeout='123')
+ resp, body = client.json_request('GET', '')
+ self.assertEqual(200, resp.status_code)
+ mock_request.assert_called_with(
'GET', 'http://example.com:8004',
allow_redirects=False,
headers={'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'python-heatclient'},
timeout=float(123))
- mock_conn.AndReturn(
- fakes.FakeHTTPResponse(
- 200, 'OK',
- {'content-type': 'application/json'},
- '{}'))
- # Replay, create client, assert
- self.m.ReplayAll()
- client = http.HTTPClient('http://example.com:8004', timeout='123')
- resp, body = client.json_request('GET', '')
- self.assertEqual(200, resp.status_code)
- self.assertEqual({}, body)
- def test_get_system_ca_file(self):
+ def test_get_system_ca_file(self, mock_request):
chosen = '/etc/ssl/certs/ca-certificates.crt'
- self.m.StubOutWithMock(os.path, 'exists')
- os.path.exists(chosen).AndReturn(chosen)
- self.m.ReplayAll()
-
- ca = http.get_system_ca_file()
- self.assertEqual(chosen, ca)
+ with mock.patch('os.path.exists') as mock_os:
+ mock_os.return_value = chosen
+ ca = http.get_system_ca_file()
+ self.assertEqual(chosen, ca)
+ mock_os.assert_called_once_with(chosen)
- def test_insecure_verify_cert_None(self):
+ def test_insecure_verify_cert_None(self, mock_request):
client = http.HTTPClient('https://foo', insecure=True)
self.assertFalse(client.verify_cert)
- def test_passed_cert_to_verify_cert(self):
+ def test_passed_cert_to_verify_cert(self, mock_request):
client = http.HTTPClient('https://foo', ca_file="NOWHERE")
self.assertEqual("NOWHERE", client.verify_cert)
- self.m.StubOutWithMock(http, 'get_system_ca_file')
- http.get_system_ca_file().AndReturn("SOMEWHERE")
- self.m.ReplayAll()
- client = http.HTTPClient('https://foo')
- self.assertEqual("SOMEWHERE", client.verify_cert)
+ with mock.patch('heatclient.common.http.get_system_ca_file') as gsf:
+ gsf.return_value = "SOMEWHERE"
+ client = http.HTTPClient('https://foo')
+ self.assertEqual("SOMEWHERE", client.verify_cert)
- def test_curl_log_i18n_headers(self):
- self.m.StubOutWithMock(logging.Logger, 'debug')
+ @mock.patch('logging.Logger.debug', return_value=None)
+ def test_curl_log_i18n_headers(self, mock_log, mock_request):
kwargs = {'headers': {'Key': b'foo\xe3\x8a\x8e'}}
- mock_logging_debug = logging.Logger.debug(
- u"curl -g -i -X GET -H 'Key: foo㊎' http://somewhere"
- )
- mock_logging_debug.AndReturn(None)
-
- self.m.ReplayAll()
-
client = http.HTTPClient('http://somewhere')
client.log_curl_request("GET", '', kwargs=kwargs)
+ mock_log.assert_called_once_with(
+ u"curl -g -i -X GET -H 'Key: foo㊎' http://somewhere")
class SessionClientTest(testtools.TestCase):
diff --git a/heatclient/tests/unit/test_event_utils.py b/heatclient/tests/unit/test_event_utils.py
index 32e4473..b080e00 100644
--- a/heatclient/tests/unit/test_event_utils.py
+++ b/heatclient/tests/unit/test_event_utils.py
@@ -18,6 +18,15 @@ from heatclient.v1 import events as hc_ev
from heatclient.v1 import resources as hc_res
+class FakeWebSocket(object):
+
+ def __init__(self, events):
+ self.events = events
+
+ def recv(self):
+ return self.events.pop(0)
+
+
class ShellTestEventUtils(testtools.TestCase):
@staticmethod
def _mock_resource(resource_id, nested_id=None):
@@ -38,7 +47,9 @@ class ShellTestEventUtils(testtools.TestCase):
@staticmethod
def _mock_event(event_id, resource_id,
resource_status='CREATE_COMPLETE'):
- ev_info = {"links": [{"href": "http://heat/foo", "rel": "self"}],
+ ev_info = {"links": [
+ {"href": "http://heat/foo", "rel": "self"},
+ {"href": "http://heat/stacks/astack", "rel": "stack"}],
"logical_resource_id": resource_id,
"physical_resource_id": resource_id,
"resource_name": resource_id,
@@ -48,6 +59,23 @@ class ShellTestEventUtils(testtools.TestCase):
"id": event_id}
return hc_ev.Event(manager=None, info=ev_info)
+ @staticmethod
+ def _mock_stack_event(event_id, stack_name,
+ stack_status='CREATE_COMPLETE'):
+ stack_id = 'abcdef'
+ ev_info = {"links": [{"href": "http://heat/foo", "rel": "self"},
+ {"href": "http://heat/stacks/%s/%s" % (stack_name,
+ stack_id),
+ "rel": "stack"}],
+ "logical_resource_id": stack_name,
+ "physical_resource_id": stack_id,
+ "resource_name": stack_name,
+ "resource_status": stack_status,
+ "resource_status_reason": "state changed",
+ "event_time": "2014-12-05T14:14:30Z",
+ "id": event_id}
+ return hc_ev.Event(manager=None, info=ev_info)
+
def test_get_nested_ids(self):
def list_stub(stack_id):
return [self._mock_resource('aresource', 'foo3/3id')]
@@ -134,7 +162,7 @@ class ShellTestEventUtils(testtools.TestCase):
@mock.patch('heatclient.common.event_utils.get_events')
def test_poll_for_events(self, ge):
ge.side_effect = [[
- self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'),
+ self._mock_stack_event('1', 'astack', 'CREATE_IN_PROGRESS'),
self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'),
self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS')
@@ -142,7 +170,7 @@ class ShellTestEventUtils(testtools.TestCase):
self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'),
self._mock_event('6', 'res_child2', 'CREATE_COMPLETE'),
self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'),
- self._mock_event('8', 'astack', 'CREATE_COMPLETE')
+ self._mock_stack_event('8', 'astack', 'CREATE_COMPLETE')
]]
stack_status, msg = event_utils.poll_for_events(
@@ -159,12 +187,41 @@ class ShellTestEventUtils(testtools.TestCase):
])
@mock.patch('heatclient.common.event_utils.get_events')
+ def test_poll_for_events_same_name(self, ge):
+ ge.side_effect = [[
+ self._mock_stack_event('1', 'mything', 'CREATE_IN_PROGRESS'),
+ self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
+ self._mock_event('3', 'mything', 'CREATE_IN_PROGRESS'),
+ ], [
+ self._mock_event('4', 'mything', 'CREATE_COMPLETE'),
+ ], [
+ self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'),
+ self._mock_stack_event('6', 'mything', 'CREATE_COMPLETE'),
+ ]]
+
+ stack_status, msg = event_utils.poll_for_events(
+ None, 'mything', action='CREATE', poll_period=0)
+ self.assertEqual('CREATE_COMPLETE', stack_status)
+ self.assertEqual('\n Stack mything CREATE_COMPLETE \n', msg)
+ ge.assert_has_calls([
+ mock.call(None, stack_id='mything', nested_depth=0, event_args={
+ 'sort_dir': 'asc', 'marker': None
+ }),
+ mock.call(None, stack_id='mything', nested_depth=0, event_args={
+ 'sort_dir': 'asc', 'marker': '3'
+ }),
+ mock.call(None, stack_id='mything', nested_depth=0, event_args={
+ 'sort_dir': 'asc', 'marker': '4'
+ })
+ ])
+
+ @mock.patch('heatclient.common.event_utils.get_events')
def test_poll_for_events_with_marker(self, ge):
ge.side_effect = [[
self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'),
self._mock_event('6', 'res_child2', 'CREATE_COMPLETE'),
self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'),
- self._mock_event('8', 'astack', 'CREATE_COMPLETE')
+ self._mock_stack_event('8', 'astack', 'CREATE_COMPLETE')
]]
stack_status, msg = event_utils.poll_for_events(
@@ -181,9 +238,9 @@ class ShellTestEventUtils(testtools.TestCase):
@mock.patch('heatclient.common.event_utils.get_events')
def test_poll_for_events_in_progress_resource(self, ge):
ge.side_effect = [[
- self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'),
+ self._mock_stack_event('1', 'astack', 'CREATE_IN_PROGRESS'),
self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
- self._mock_event('3', 'astack', 'CREATE_COMPLETE')
+ self._mock_stack_event('3', 'astack', 'CREATE_COMPLETE')
]]
stack_status, msg = event_utils.poll_for_events(
@@ -194,7 +251,7 @@ class ShellTestEventUtils(testtools.TestCase):
@mock.patch('heatclient.common.event_utils.get_events')
def test_poll_for_events_failed(self, ge):
ge.side_effect = [[
- self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'),
+ self._mock_stack_event('1', 'astack', 'CREATE_IN_PROGRESS'),
self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'),
self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS')
@@ -202,7 +259,7 @@ class ShellTestEventUtils(testtools.TestCase):
self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'),
self._mock_event('6', 'res_child2', 'CREATE_FAILED'),
self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'),
- self._mock_event('8', 'astack', 'CREATE_FAILED')
+ self._mock_stack_event('8', 'astack', 'CREATE_FAILED')
]]
stack_status, msg = event_utils.poll_for_events(
@@ -213,7 +270,7 @@ class ShellTestEventUtils(testtools.TestCase):
@mock.patch('heatclient.common.event_utils.get_events')
def test_poll_for_events_no_action(self, ge):
ge.side_effect = [[
- self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'),
+ self._mock_stack_event('1', 'astack', 'CREATE_IN_PROGRESS'),
self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'),
self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS')
@@ -221,7 +278,7 @@ class ShellTestEventUtils(testtools.TestCase):
self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'),
self._mock_event('6', 'res_child2', 'CREATE_FAILED'),
self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'),
- self._mock_event('8', 'astack', 'FOO_FAILED')
+ self._mock_stack_event('8', 'astack', 'FOO_FAILED')
]]
stack_status, msg = event_utils.poll_for_events(
@@ -235,7 +292,7 @@ class ShellTestEventUtils(testtools.TestCase):
mock_client.stacks.get.return_value.stack_status = 'CREATE_FAILED'
ge.side_effect = [[
- self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'),
+ self._mock_stack_event('1', 'astack', 'CREATE_IN_PROGRESS'),
self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'),
self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'),
self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS')
@@ -245,3 +302,36 @@ class ShellTestEventUtils(testtools.TestCase):
mock_client, 'astack', action='CREATE', poll_period=0)
self.assertEqual('CREATE_FAILED', stack_status)
self.assertEqual('\n Stack astack CREATE_FAILED \n', msg)
+
+ def test_wait_for_events(self):
+ ws = FakeWebSocket([
+ {'body': {
+ 'timestamp': '2014-01-06T16:14:26Z',
+ 'payload': {'resource_action': 'CREATE',
+ 'resource_status': 'COMPLETE',
+ 'resource_name': 'mystack',
+ 'physical_resource_id': 'stackid1',
+ 'stack_id': 'stackid1'}}}])
+ stack_status, msg = event_utils.wait_for_events(ws, 'mystack')
+ self.assertEqual('CREATE_COMPLETE', stack_status)
+ self.assertEqual('\n Stack mystack CREATE_COMPLETE \n', msg)
+
+ def test_wait_for_events_failed(self):
+ ws = FakeWebSocket([
+ {'body': {
+ 'timestamp': '2014-01-06T16:14:23Z',
+ 'payload': {'resource_action': 'CREATE',
+ 'resource_status': 'IN_PROGRESS',
+ 'resource_name': 'mystack',
+ 'physical_resource_id': 'stackid1',
+ 'stack_id': 'stackid1'}}},
+ {'body': {
+ 'timestamp': '2014-01-06T16:14:26Z',
+ 'payload': {'resource_action': 'CREATE',
+ 'resource_status': 'FAILED',
+ 'resource_name': 'mystack',
+ 'physical_resource_id': 'stackid1',
+ 'stack_id': 'stackid1'}}}])
+ stack_status, msg = event_utils.wait_for_events(ws, 'mystack')
+ self.assertEqual('CREATE_FAILED', stack_status)
+ self.assertEqual('\n Stack mystack CREATE_FAILED \n', msg)
diff --git a/heatclient/tests/unit/test_events.py b/heatclient/tests/unit/test_events.py
index f6071a5..b63aebe 100644
--- a/heatclient/tests/unit/test_events.py
+++ b/heatclient/tests/unit/test_events.py
@@ -13,7 +13,6 @@
# under the License.
import mock
-import mox
import testtools
from heatclient.common import utils
@@ -22,39 +21,39 @@ from heatclient.v1 import events
class EventManagerTest(testtools.TestCase):
- def setUp(self):
- super(EventManagerTest, self).setUp()
- self.m = mox.Mox()
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
def test_list_event(self):
stack_id = 'teststack',
resource_name = 'testresource'
manager = events.EventManager(None)
- self.m.StubOutWithMock(manager, '_resolve_stack_id')
- manager._resolve_stack_id(stack_id).AndReturn('teststack/abcd1234')
- self.m.ReplayAll()
- manager._list = mock.MagicMock()
- manager.list(stack_id, resource_name)
- # Make sure url is correct.
- manager._list.assert_called_once_with('/stacks/teststack%2Fabcd1234/'
- 'resources/testresource/events',
- "events")
+ with mock.patch('heatclient.v1.events.EventManager._resolve_stack_id')\
+ as mock_re:
+ mock_re.return_value = 'teststack/abcd1234'
+
+ manager._list = mock.MagicMock()
+ manager.list(stack_id, resource_name)
+ # Make sure url is correct.
+ manager._list.assert_called_once_with(
+ '/stacks/teststack/abcd1234/'
+ 'resources/testresource/events',
+ "events")
+ mock_re.assert_called_once_with(stack_id)
def test_list_event_with_unicode_resource_name(self):
stack_id = 'teststack',
resource_name = u'\u5de5\u4f5c'
manager = events.EventManager(None)
- self.m.StubOutWithMock(manager, '_resolve_stack_id')
- manager._resolve_stack_id(stack_id).AndReturn('teststack/abcd1234')
- self.m.ReplayAll()
- manager._list = mock.MagicMock()
- manager.list(stack_id, resource_name)
- # Make sure url is correct.
- manager._list.assert_called_once_with('/stacks/teststack%2Fabcd1234/'
- 'resources/%E5%B7%A5%E4%BD%9C/'
- 'events', "events")
+ with mock.patch('heatclient.v1.events.EventManager._resolve_stack_id')\
+ as mock_re:
+ mock_re.return_value = 'teststack/abcd1234'
+
+ manager._list = mock.MagicMock()
+ manager.list(stack_id, resource_name)
+ # Make sure url is correct.
+ manager._list.assert_called_once_with(
+ '/stacks/teststack/abcd1234/'
+ 'resources/%E5%B7%A5%E4%BD%9C/'
+ 'events', "events")
+ mock_re.assert_called_once_with(stack_id)
def test_list_event_with_none_resource_name(self):
stack_id = 'teststack',
@@ -75,28 +74,33 @@ class EventManagerTest(testtools.TestCase):
'resource_status': 'COMPLETE'
}}
manager = events.EventManager(None)
- self.m.StubOutWithMock(manager, '_resolve_stack_id')
- manager._resolve_stack_id(stack_id).AndReturn('teststack/abcd1234')
- self.m.ReplayAll()
- manager._list = mock.MagicMock()
- manager.list(stack_id, resource_name, **kwargs)
- # Make sure url is correct.
- self.assertEqual(1, manager._list.call_count)
- args = manager._list.call_args
- self.assertEqual(2, len(args[0]))
- url, param = args[0]
- self.assertEqual("events", param)
- base_url, query_params = utils.parse_query_url(url)
- expected_base_url = ('/stacks/teststack%2Fabcd1234/'
- 'resources/testresource/events')
- self.assertEqual(expected_base_url, base_url)
- expected_query_dict = {'marker': ['6d6935f4-0ae5'],
- 'limit': ['2'],
- 'resource_action': ['CREATE'],
- 'resource_status': ['COMPLETE']}
- self.assertEqual(expected_query_dict, query_params)
-
- def test_get_event(self):
+ manager = events.EventManager(None)
+ with mock.patch('heatclient.v1.events.EventManager._resolve_stack_id')\
+ as mock_re:
+ mock_re.return_value = 'teststack/abcd1234'
+
+ manager._list = mock.MagicMock()
+ manager.list(stack_id, resource_name, **kwargs)
+ # Make sure url is correct.
+ self.assertEqual(1, manager._list.call_count)
+ args = manager._list.call_args
+ self.assertEqual(2, len(args[0]))
+ url, param = args[0]
+ self.assertEqual("events", param)
+ base_url, query_params = utils.parse_query_url(url)
+ expected_base_url = ('/stacks/teststack/abcd1234/'
+ 'resources/testresource/events')
+ self.assertEqual(expected_base_url, base_url)
+ expected_query_dict = {'marker': ['6d6935f4-0ae5'],
+ 'limit': ['2'],
+ 'resource_action': ['CREATE'],
+ 'resource_status': ['COMPLETE']}
+ self.assertEqual(expected_query_dict, query_params)
+ mock_re.assert_called_once_with(stack_id)
+
+ @mock.patch('heatclient.v1.events.EventManager._resolve_stack_id')
+ @mock.patch('heatclient.common.utils.get_response_body')
+ def test_get_event(self, mock_utils, mock_re):
fields = {'stack_id': 'teststack',
'resource_name': 'testresource',
'event_id': '1'}
@@ -106,7 +110,7 @@ class EventManagerTest(testtools.TestCase):
def json_request(self, *args, **kwargs):
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource/events/1')
assert args == expect
return {}, {'event': []}
@@ -116,15 +120,14 @@ class EventManagerTest(testtools.TestCase):
manager = events.EventManager(FakeAPI())
with mock.patch('heatclient.v1.events.Event'):
- self.m.StubOutWithMock(manager, '_resolve_stack_id')
- self.m.StubOutWithMock(utils, 'get_response_body')
- utils.get_response_body(mox.IgnoreArg()).AndReturn({'event': []})
- manager._resolve_stack_id('teststack').AndReturn(
- 'teststack/abcd1234')
- self.m.ReplayAll()
+ mock_utils.return_value = {'event': []}
+ mock_re.return_value = 'teststack/abcd1234'
manager.get(**fields)
+ mock_re.assert_called_once_with('teststack')
- def test_get_event_with_unicode_resource_name(self):
+ @mock.patch('heatclient.v1.events.EventManager._resolve_stack_id')
+ @mock.patch('heatclient.common.utils.get_response_body')
+ def test_get_event_with_unicode_resource_name(self, mock_utils, mock_re):
fields = {'stack_id': 'teststack',
'resource_name': u'\u5de5\u4f5c',
'event_id': '1'}
@@ -134,7 +137,7 @@ class EventManagerTest(testtools.TestCase):
def json_request(self, *args, **kwargs):
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/%E5%B7%A5%E4%BD%9C/events/1')
assert args == expect
return {}, {'event': []}
@@ -144,10 +147,7 @@ class EventManagerTest(testtools.TestCase):
manager = events.EventManager(FakeAPI())
with mock.patch('heatclient.v1.events.Event'):
- self.m.StubOutWithMock(manager, '_resolve_stack_id')
- self.m.StubOutWithMock(utils, 'get_response_body')
- utils.get_response_body(mox.IgnoreArg()).AndReturn({'event': []})
- manager._resolve_stack_id('teststack').AndReturn(
- 'teststack/abcd1234')
- self.m.ReplayAll()
+ mock_utils.return_value = {'event': []}
+ mock_re.return_value = 'teststack/abcd1234'
manager.get(**fields)
+ mock_re.assert_called_once_with('teststack')
diff --git a/heatclient/tests/unit/test_resources.py b/heatclient/tests/unit/test_resources.py
index b3c5c30..96e8203 100644
--- a/heatclient/tests/unit/test_resources.py
+++ b/heatclient/tests/unit/test_resources.py
@@ -73,7 +73,7 @@ class ResourceManagerTest(testtools.TestCase):
fields = {'stack_id': 'teststack',
'resource_name': 'testresource'}
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource')
key = 'resource'
@@ -86,7 +86,7 @@ class ResourceManagerTest(testtools.TestCase):
'resource_name': 'testresource',
'with_attr': ['attr_a', 'attr_b']}
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource?with_attr=attr_a&with_attr=attr_b')
key = 'resource'
@@ -98,7 +98,7 @@ class ResourceManagerTest(testtools.TestCase):
fields = {'stack_id': 'teststack',
'resource_name': u'\u5de5\u4f5c'}
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/%E5%B7%A5%E4%BD%9C')
key = 'resource'
@@ -154,7 +154,7 @@ class ResourceManagerTest(testtools.TestCase):
fields = {'stack_id': 'teststack',
'resource_name': 'testresource'}
expect = ('GET',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource/metadata')
key = 'metadata'
@@ -192,7 +192,7 @@ class ResourceManagerTest(testtools.TestCase):
'resource_name': 'testresource',
'data': 'Some content'}
expect = ('POST',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource/signal')
key = 'signal'
@@ -206,7 +206,7 @@ class ResourceManagerTest(testtools.TestCase):
'mark_unhealthy': 'True',
'resource_status_reason': 'Anything'}
expect = ('PATCH',
- '/stacks/teststack%2Fabcd1234/resources'
+ '/stacks/teststack/abcd1234/resources'
'/testresource')
key = 'mark_unhealthy'
diff --git a/heatclient/tests/unit/test_shell.py b/heatclient/tests/unit/test_shell.py
index 383ee2c..b9ec014 100644
--- a/heatclient/tests/unit/test_shell.py
+++ b/heatclient/tests/unit/test_shell.py
@@ -32,6 +32,7 @@ import testscenarios
import testtools
import yaml
+from heatclient._i18n import _
from heatclient.common import http
from heatclient.common import utils
from heatclient import exc
@@ -126,25 +127,25 @@ class TestCase(testtools.TestCase):
mockfixture = self.useFixture(mockpatch.Patch(target, **kwargs))
return mockfixture.mock
- def stack_list_resp_dict(self, show_nested=False):
- resp_dict = {"stacks": [
- {
- "id": "1",
- "stack_name": "teststack",
- "stack_owner": "testowner",
- "project": "testproject",
- "stack_status": 'CREATE_COMPLETE',
- "creation_time": "2012-10-25T01:58:47Z"
- },
- {
- "id": "2",
- "stack_name": "teststack2",
- "stack_owner": "testowner",
- "project": "testproject",
- "stack_status": 'IN_PROGRESS',
- "creation_time": "2012-10-25T01:58:47Z"
- }]
- }
+ def stack_list_resp_dict(self, show_nested=False, include_project=False):
+ stack1 = {
+ "id": "1",
+ "stack_name": "teststack",
+ "stack_owner": "testowner",
+ "stack_status": 'CREATE_COMPLETE',
+ "creation_time": "2012-10-25T01:58:47Z"}
+ stack2 = {
+ "id": "2",
+ "stack_name": "teststack2",
+ "stack_owner": "testowner",
+ "stack_status": 'IN_PROGRESS',
+ "creation_time": "2012-10-25T01:58:47Z"
+ }
+ if include_project:
+ stack1['project'] = 'testproject'
+ stack1['project'] = 'testproject'
+
+ resp_dict = {"stacks": [stack1, stack2]}
if show_nested:
nested = {
"id": "3",
@@ -153,6 +154,8 @@ class TestCase(testtools.TestCase):
"creation_time": "2012-10-25T01:58:47Z",
"parent": "theparentof3"
}
+ if include_project:
+ nested['project'] = 'testproject'
resp_dict["stacks"].append(nested)
return resp_dict
@@ -211,7 +214,7 @@ class TestCase(testtools.TestCase):
{"href": "http://heat.example.com:8004/foo3",
"rel": "stack"}],
"logical_resource_id": "aResource",
- "physical_resource_id": None,
+ "physical_resource_id": 'foo3',
"resource_name": stack_name,
"resource_status": "%s_IN_PROGRESS" % action,
"resource_status_reason": "state changed"})
@@ -225,7 +228,7 @@ class TestCase(testtools.TestCase):
{"href": "http://heat.example.com:8004/foo3",
"rel": "stack"}],
"logical_resource_id": "aResource",
- "physical_resource_id": None,
+ "physical_resource_id": 'foo3',
"resource_name": stack_name,
"resource_status": "%s_%s" % (action, final_state),
"resource_status_reason": "state changed"})
@@ -561,7 +564,7 @@ class ShellTestNoMox(TestCase):
rsrc_eventid2=eventid2
)
- self.requests.get('http://heat.example.com/stacks/myStack%2F60f83b5e/'
+ self.requests.get('http://heat.example.com/stacks/myStack/60f83b5e/'
'resources/myDeployment/events',
headers={'Content-Type': 'application/json'},
json=resp_dict)
@@ -618,7 +621,8 @@ class ShellTestEndpointType(TestCase):
'region_name': '',
'username': 'username',
'password': 'password',
- 'include_pass': False
+ 'include_pass': False,
+ 'endpoint_override': mox.IgnoreArg(),
}
http._construct_http_client(**kwargs)
heatclient.v1.shell.do_stack_list(mox.IgnoreArg(), mox.IgnoreArg())
@@ -637,7 +641,8 @@ class ShellTestEndpointType(TestCase):
'region_name': '',
'username': 'username',
'password': 'password',
- 'include_pass': False
+ 'include_pass': False,
+ 'endpoint_override': mox.IgnoreArg(),
}
http._construct_http_client(**kwargs)
heatclient.v1.shell.do_stack_list(mox.IgnoreArg(), mox.IgnoreArg())
@@ -658,7 +663,8 @@ class ShellTestEndpointType(TestCase):
'region_name': '',
'username': 'username',
'password': 'password',
- 'include_pass': False
+ 'include_pass': False,
+ 'endpoint_override': mox.IgnoreArg(),
}
http._construct_http_client(**kwargs)
heatclient.v1.shell.do_stack_list(mox.IgnoreArg(), mox.IgnoreArg())
@@ -2220,6 +2226,65 @@ class ShellTestUserPass(ShellBase):
resp = self.shell('snapshot-show teststack/1 2')
self.assertEqual(resp_dict, jsonutils.loads(resp))
+ # the main thing this @mock.patch is doing here is keeping
+ # sys.stdin untouched for later tests
+ @mock.patch('sys.stdin', new_callable=six.StringIO)
+ def test_snapshot_delete_prompt_with_tty(self, ms):
+ self.register_keystone_auth_fixture()
+ resp_dict = {"snapshot": {
+ "id": "2",
+ "creation_time": "2012-10-25T01:58:47Z"
+ }}
+
+ mock_stdin = mock.Mock()
+ mock_stdin.isatty = mock.Mock()
+ mock_stdin.isatty.return_value = True
+ mock_stdin.readline = mock.Mock()
+ mock_stdin.readline.return_value = 'n'
+ sys.stdin = mock_stdin
+
+ self.mock_request_delete('/stacks/teststack/1/snapshots/2', resp_dict)
+
+ self.m.ReplayAll()
+
+ resp = self.shell('snapshot-delete teststack/1 2')
+ resp_text = ('Are you sure you want to delete the snapshot of '
+ 'this stack [Y/N]?')
+ self.assertEqual(resp_text, resp)
+ self.m.ReplayAll()
+
+ mock_stdin.readline.return_value = 'Y'
+ resp = self.shell('snapshot-delete teststack/1 2')
+ msg = _("Request to delete the snapshot 2 of the stack "
+ "teststack/1 has been accepted.")
+ self.assertRegex(resp, msg)
+
+ # the main thing this @mock.patch is doing here is keeping
+ # sys.stdin untouched for later tests
+ @mock.patch('sys.stdin', new_callable=six.StringIO)
+ def test_snapshot_delete_prompt_with_tty_y(self, ms):
+ self.register_keystone_auth_fixture()
+ resp_dict = {"snapshot": {
+ "id": "2",
+ "creation_time": "2012-10-25T01:58:47Z"
+ }}
+
+ mock_stdin = mock.Mock()
+ mock_stdin.isatty = mock.Mock()
+ mock_stdin.isatty.return_value = True
+ mock_stdin.readline = mock.Mock()
+ mock_stdin.readline.return_value = ''
+ sys.stdin = mock_stdin
+
+ self.mock_request_delete('/stacks/teststack/1/snapshots/2', resp_dict)
+
+ self.m.ReplayAll()
+ # -y from the shell should skip the n/y prompt
+ resp = self.shell('snapshot-delete -y teststack/1 2')
+ msg = _("Request to delete the snapshot 2 of the stack "
+ "teststack/1 has been accepted.")
+ self.assertRegex(resp, msg)
+
def test_snapshot_delete(self):
self.register_keystone_auth_fixture()
@@ -2231,7 +2296,9 @@ class ShellTestUserPass(ShellBase):
self.m.ReplayAll()
resp = self.shell('snapshot-delete teststack/1 2')
- self.assertEqual("", resp)
+ msg = _("Request to delete the snapshot 2 of the stack "
+ "teststack/1 has been accepted.")
+ self.assertRegex(resp, msg)
def test_stack_restore(self):
self.register_keystone_auth_fixture()
@@ -2617,9 +2684,9 @@ class ShellTestEvents(ShellBase):
resource_name = 'testresource/1'
self.mock_request_get(
'/stacks/%s/resources/%s/events?sort_dir=asc' % (
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')),
+ resource_name))),
resp_dict)
self.m.ReplayAll()
@@ -2693,10 +2760,10 @@ class ShellTestEvents(ShellBase):
self.mock_request_get(
'/stacks/%s/resources/%s/events/%s' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), ''),
- parse.quote(self.event_id_one, '')
+ resource_name)),
+ parse.quote(self.event_id_one)
),
resp_dict)
@@ -3276,9 +3343,9 @@ class ShellTestResources(ShellBase):
self.mock_request_get(
'/stacks/%s/resources/%s?with_attr=attr_a&with_attr=attr_b' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
), resp_dict)
self.m.ReplayAll()
@@ -3318,9 +3385,9 @@ class ShellTestResources(ShellBase):
self.mock_request_post(
'/stacks/%s/resources/%s/signal' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
data={'message': 'Content'}
@@ -3340,9 +3407,9 @@ class ShellTestResources(ShellBase):
self.mock_request_post(
'/stacks/%s/resources/%s/signal' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
data=None
@@ -3400,9 +3467,9 @@ class ShellTestResources(ShellBase):
self.mock_request_post(
'/stacks/%s/resources/%s/signal' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
data={'message': 'Content'}
@@ -3425,9 +3492,9 @@ class ShellTestResources(ShellBase):
self.mock_request_patch(
'/stacks/%s/resources/%s' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
req_headers=False,
@@ -3448,9 +3515,9 @@ class ShellTestResources(ShellBase):
self.mock_request_patch(
'/stacks/%s/resources/%s' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
req_headers=False,
@@ -3471,9 +3538,9 @@ class ShellTestResources(ShellBase):
self.mock_request_patch(
'/stacks/%s/resources/%s' %
(
- parse.quote(stack_id, ''),
+ parse.quote(stack_id),
parse.quote(encodeutils.safe_encode(
- resource_name), '')
+ resource_name))
),
'',
req_headers=False,
@@ -4206,7 +4273,7 @@ class MockShellTestUserPass(MockShellBase):
def test_stack_list_with_args(self):
self.register_keystone_auth_fixture()
- resp_dict = self.stack_list_resp_dict()
+ resp_dict = self.stack_list_resp_dict(include_project=True)
resp = fakes.FakeHTTPResponse(
200,
'success, you',
diff --git a/heatclient/tests/unit/test_template_utils.py b/heatclient/tests/unit/test_template_utils.py
index 7de72b5..a48e0b3 100644
--- a/heatclient/tests/unit/test_template_utils.py
+++ b/heatclient/tests/unit/test_template_utils.py
@@ -15,10 +15,9 @@ import base64
import json
import tempfile
-import mox
+import mock
import six
from six.moves.urllib import error
-from six.moves.urllib import request
import testtools
from testtools import matchers
import yaml
@@ -32,30 +31,24 @@ class ShellEnvironmentTest(testtools.TestCase):
template_a = b'{"heat_template_version": "2013-05-23"}'
- def setUp(self):
- super(ShellEnvironmentTest, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
def collect_links(self, env, content, url, env_base_url=''):
-
jenv = yaml.safe_load(env)
files = {}
if url:
- self.m.StubOutWithMock(request, 'urlopen')
- request.urlopen(url).AndReturn(six.BytesIO(content))
- request.urlopen(url).AndReturn(six.BytesIO(content))
- self.m.ReplayAll()
-
- template_utils.resolve_environment_urls(
- jenv.get('resource_registry'), files, env_base_url)
- if url:
- self.assertEqual(content.decode('utf-8'), files[url])
+ def side_effect(args):
+ if url == args:
+ return six.BytesIO(content)
+ with mock.patch('six.moves.urllib.request.urlopen') as mock_url:
+ mock_url.side_effect = side_effect
+ template_utils.resolve_environment_urls(
+ jenv.get('resource_registry'), files, env_base_url)
+ self.assertEqual(content.decode('utf-8'), files[url])
+ else:
+ template_utils.resolve_environment_urls(
+ jenv.get('resource_registry'), files, env_base_url)
- def test_ignore_env_keys(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_ignore_env_keys(self, mock_url):
env_file = '/home/my/dir/env.yaml'
env = b'''
resource_registry:
@@ -64,9 +57,7 @@ class ShellEnvironmentTest(testtools.TestCase):
hooks: pre_create
restricted_actions: replace
'''
- request.urlopen('file://%s' % env_file).AndReturn(
- six.BytesIO(env))
- self.m.ReplayAll()
+ mock_url.return_value = six.BytesIO(env)
_, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual(
@@ -74,24 +65,18 @@ class ShellEnvironmentTest(testtools.TestCase):
u'bar': {u'hooks': u'pre_create',
u'restricted_actions': u'replace'}}}},
env_dict)
- self.m.VerifyAll()
+ mock_url.assert_called_with('file://%s' % env_file)
- def test_process_environment_file(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_file(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env = b'''
resource_registry:
"OS::Thingy": "file:///home/b/a.yaml"
'''
-
- request.urlopen('file://%s' % env_file).AndReturn(
- six.BytesIO(env))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env), six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
files, env_dict = template_utils.process_environment_and_files(
env_file)
@@ -101,10 +86,15 @@ class ShellEnvironmentTest(testtools.TestCase):
env_dict)
self.assertEqual(self.template_a.decode('utf-8'),
files['file:///home/b/a.yaml'])
+ mock_url.assert_has_calls([
+ mock.call('file://%s' % env_file),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/a.yaml')
+ ])
- def test_process_environment_relative_file(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_relative_file(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = b'''
@@ -112,13 +102,8 @@ class ShellEnvironmentTest(testtools.TestCase):
"OS::Thingy": a.yaml
'''
- request.urlopen(env_url).AndReturn(
- six.BytesIO(env))
- request.urlopen('file:///home/my/dir/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/my/dir/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env), six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
self.assertEqual(
env_url,
@@ -136,24 +121,23 @@ class ShellEnvironmentTest(testtools.TestCase):
env_dict)
self.assertEqual(self.template_a.decode('utf-8'),
files['file:///home/my/dir/a.yaml'])
+ mock_url.assert_has_calls([
+ mock.call(env_url),
+ mock.call('file:///home/my/dir/a.yaml'),
+ mock.call('file:///home/my/dir/a.yaml')
+ ])
- def test_process_environment_relative_file_up(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_relative_file_up(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = b'''
resource_registry:
"OS::Thingy": ../bar/a.yaml
'''
-
- request.urlopen(env_url).AndReturn(
- six.BytesIO(env))
- request.urlopen('file:///home/my/bar/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/my/bar/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env), six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
env_url = 'file://%s' % env_file
self.assertEqual(
@@ -172,20 +156,22 @@ class ShellEnvironmentTest(testtools.TestCase):
env_dict)
self.assertEqual(self.template_a.decode('utf-8'),
files['file:///home/my/bar/a.yaml'])
-
- def test_process_environment_url(self):
+ mock_url.assert_has_calls([
+ mock.call(env_url),
+ mock.call('file:///home/my/bar/a.yaml'),
+ mock.call('file:///home/my/bar/a.yaml')
+ ])
+
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_url(self, mock_url):
env = b'''
resource_registry:
"OS::Thingy": "a.yaml"
'''
url = 'http://no.where/some/path/to/file.yaml'
tmpl_url = 'http://no.where/some/path/to/a.yaml'
-
- self.m.StubOutWithMock(request, 'urlopen')
- request.urlopen(url).AndReturn(six.BytesIO(env))
- request.urlopen(tmpl_url).AndReturn(six.BytesIO(self.template_a))
- request.urlopen(tmpl_url).AndReturn(six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env), six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
files, env_dict = template_utils.process_environment_and_files(
url)
@@ -193,30 +179,34 @@ class ShellEnvironmentTest(testtools.TestCase):
self.assertEqual({'resource_registry': {'OS::Thingy': tmpl_url}},
env_dict)
self.assertEqual(self.template_a.decode('utf-8'), files[tmpl_url])
+ mock_url.assert_has_calls([
+ mock.call(url),
+ mock.call(tmpl_url),
+ mock.call(tmpl_url)
+ ])
- def test_process_environment_empty_file(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_empty_file(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env = b''
-
- request.urlopen('file://%s' % env_file).AndReturn(six.BytesIO(env))
- self.m.ReplayAll()
+ mock_url.return_value = six.BytesIO(env)
files, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual({}, env_dict)
self.assertEqual({}, files)
+ mock_url.assert_called_with('file://%s' % env_file)
def test_no_process_environment_and_files(self):
files, env = template_utils.process_environment_and_files()
self.assertEqual({}, env)
self.assertEqual({}, files)
- def test_process_multiple_environments_and_files(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_multiple_environments_and_files(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file1 = '/home/my/dir/env1.yaml'
env_file2 = '/home/my/dir/env2.yaml'
@@ -233,19 +223,12 @@ class ShellEnvironmentTest(testtools.TestCase):
"OS::Thingy2": "file:///home/b/b.yaml"
'''
- request.urlopen('file://%s' % env_file1).AndReturn(
- six.BytesIO(env1))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file://%s' % env_file2).AndReturn(
- six.BytesIO(env2))
- request.urlopen('file:///home/b/b.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/b.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env1),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(env2),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
files, env = template_utils.process_multiple_environments_and_files(
[env_file1, env_file2])
@@ -263,10 +246,18 @@ class ShellEnvironmentTest(testtools.TestCase):
files['file:///home/b/a.yaml'])
self.assertEqual(self.template_a.decode('utf-8'),
files['file:///home/b/b.yaml'])
+ mock_url.assert_has_calls([
+ mock.call('file://%s' % env_file1),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file://%s' % env_file2),
+ mock.call('file:///home/b/b.yaml'),
+ mock.call('file:///home/b/b.yaml')
+ ])
+
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_multiple_environments_default_resources(self, mock_url):
- def test_process_multiple_environments_default_resources(self):
-
- self.m.StubOutWithMock(request, 'urlopen')
env_file1 = '/home/my/dir/env1.yaml'
env_file2 = '/home/my/dir/env2.yaml'
@@ -286,28 +277,16 @@ class ShellEnvironmentTest(testtools.TestCase):
resource2:
"OS::Thingy4": "file:///home/b/b.yaml"
'''
-
- request.urlopen('file://%s' % env_file1).InAnyOrder().AndReturn(
- six.BytesIO(env1))
- request.urlopen('file:///home/b/a.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/b.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/a.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/b.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file://%s' % env_file2).InAnyOrder().AndReturn(
- six.BytesIO(env2))
- request.urlopen('file:///home/b/a.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/b.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/a.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/b.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env1),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(env2),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
files, env = template_utils.process_multiple_environments_and_files(
[env_file1, env_file2])
@@ -331,6 +310,19 @@ class ShellEnvironmentTest(testtools.TestCase):
files['file:///home/b/a.yaml'])
self.assertEqual(self.template_a.decode('utf-8'),
files['file:///home/b/b.yaml'])
+ mock_url.assert_has_calls([
+ mock.call('file://%s' % env_file1),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/b.yaml'),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/b.yaml'),
+ mock.call('file://%s' % env_file2),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/b.yaml'),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/b.yaml'),
+
+ ], any_order=True)
def test_no_process_multiple_environments_and_files(self):
files, env = template_utils.process_multiple_environments_and_files()
@@ -347,8 +339,6 @@ class ShellEnvironmentTest(testtools.TestCase):
"OS::Thingy1": "b/a.yaml"
'''
- self.m.ReplayAll()
-
self.object_requested = False
def env_path_is_object(object_url):
@@ -376,9 +366,9 @@ class ShellEnvironmentTest(testtools.TestCase):
self.assertEqual(self.template_a.decode('utf-8'),
files['http://no.where/path/to/b/a.yaml'])
- def test_process_multiple_environments_and_files_tracker(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_multiple_environments_and_files_tracker(self, mock_url):
# Setup
- self.m.StubOutWithMock(request, 'urlopen')
env_file1 = '/home/my/dir/env1.yaml'
env1 = b'''
@@ -387,13 +377,9 @@ class ShellEnvironmentTest(testtools.TestCase):
resource_registry:
"OS::Thingy1": "file:///home/b/a.yaml"
'''
- request.urlopen('file://%s' % env_file1).AndReturn(
- six.BytesIO(env1))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/b/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env1),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
# Test
env_file_list = []
@@ -414,24 +400,25 @@ class ShellEnvironmentTest(testtools.TestCase):
self.assertIn('file:///home/my/dir/env1.yaml', files)
self.assertEqual(expected_env,
json.loads(files['file:///home/my/dir/env1.yaml']))
+ mock_url.assert_has_calls([
+ mock.call('file://%s' % env_file1),
+ mock.call('file:///home/b/a.yaml'),
+ mock.call('file:///home/b/a.yaml'),
- def test_process_environment_relative_file_tracker(self):
+ ])
+
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_process_environment_relative_file_tracker(self, mock_url):
- self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = b'''
resource_registry:
"OS::Thingy": a.yaml
'''
-
- request.urlopen(env_url).AndReturn(
- six.BytesIO(env))
- request.urlopen('file:///home/my/dir/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- request.urlopen('file:///home/my/dir/a.yaml').AndReturn(
- six.BytesIO(self.template_a))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(env),
+ six.BytesIO(self.template_a),
+ six.BytesIO(self.template_a)]
self.assertEqual(
env_url,
@@ -454,6 +441,12 @@ class ShellEnvironmentTest(testtools.TestCase):
self.assertEqual(['file:///home/my/dir/env.yaml'], env_file_list)
self.assertEqual(json.dumps(expected_env),
files['file:///home/my/dir/env.yaml'])
+ mock_url.assert_has_calls([
+ mock.call(env_url),
+ mock.call('file:///home/my/dir/a.yaml'),
+ mock.call('file:///home/my/dir/a.yaml'),
+
+ ])
def test_global_files(self):
url = 'file:///home/b/a.yaml'
@@ -538,13 +531,6 @@ class ShellEnvironmentTest(testtools.TestCase):
class TestGetTemplateContents(testtools.TestCase):
- def setUp(self):
- super(TestGetTemplateContents, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
def test_get_template_contents_file(self):
with tempfile.NamedTemporaryFile() as tmpl_file:
tmpl = (b'{"AWSTemplateFormatVersion" : "2010-09-09",'
@@ -611,23 +597,22 @@ class TestGetTemplateContents(testtools.TestCase):
matchers.MatchesRegex(
'Error parsing template file://%s ' % tmpl_file.name))
- def test_get_template_contents_url(self):
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_get_template_contents_url(self, mock_url):
tmpl = b'{"AWSTemplateFormatVersion" : "2010-09-09", "foo": "bar"}'
url = 'http://no.where/path/to/a.yaml'
- self.m.StubOutWithMock(request, 'urlopen')
- request.urlopen(url).AndReturn(six.BytesIO(tmpl))
- self.m.ReplayAll()
+ mock_url.return_value = six.BytesIO(tmpl)
files, tmpl_parsed = template_utils.get_template_contents(
template_url=url)
self.assertEqual({"AWSTemplateFormatVersion": "2010-09-09",
"foo": "bar"}, tmpl_parsed)
self.assertEqual({}, files)
+ mock_url.assert_called_with(url)
def test_get_template_contents_object(self):
tmpl = '{"AWSTemplateFormatVersion" : "2010-09-09", "foo": "bar"}'
url = 'http://no.where/path/to/a.yaml'
- self.m.ReplayAll()
self.object_requested = False
@@ -652,7 +637,6 @@ class TestGetTemplateContents(testtools.TestCase):
'"FooBar": {'
'"type": "foo/bar.yaml"}}}')
url = 'http://no.where/path/to/a.yaml'
- self.m.ReplayAll()
self.object_requested = False
@@ -685,15 +669,15 @@ class TestGetTemplateContents(testtools.TestCase):
[{'path': '/tmp/%s' % filename,
'content': {'get_file': url},
'encoding': 'b64'}]}}}}}
- self.m.StubOutWithMock(request, 'urlopen')
- raw_content = base64.decodestring(content)
- response = six.BytesIO(raw_content)
- request.urlopen(url).AndReturn(response)
- self.m.ReplayAll()
- files = {}
- template_utils.resolve_template_get_files(
- template, files, base_url)
- self.assertEqual({url: content}, files)
+ with mock.patch('six.moves.urllib.request.urlopen') as mock_url:
+ raw_content = base64.decodestring(content)
+ response = six.BytesIO(raw_content)
+ mock_url.return_value = response
+ files = {}
+ template_utils.resolve_template_get_files(
+ template, files, base_url)
+ self.assertEqual({url: content}, files)
+ mock_url.assert_called_with(url)
def test_get_zip_content(self):
filename = 'heat.zip'
@@ -746,6 +730,7 @@ ABOkDAABQSwUGAAAAAAEAAQBOAAAARwAAAAAA\n'''
self.check_non_utf8_content(filename=filename, content=content)
+@mock.patch('six.moves.urllib.request.urlopen')
class TestTemplateGetFileFunctions(testtools.TestCase):
hot_template = b'''heat_template_version: 2013-05-23
@@ -769,49 +754,21 @@ resources:
ignored_none: {get_file: }
'''
- def setUp(self):
- super(TestTemplateGetFileFunctions, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
- def test_hot_template(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ def test_hot_template(self, mock_url):
tmpl_file = '/home/my/dir/template.yaml'
url = 'file:///home/my/dir/template.yaml'
- request.urlopen(url).AndReturn(
- six.BytesIO(self.hot_template))
- request.urlopen(
- 'http://localhost/bar.yaml').InAnyOrder().AndReturn(
- six.BytesIO(b'bar contents'))
- request.urlopen(
- 'file:///home/my/dir/foo.yaml').InAnyOrder().AndReturn(
- six.BytesIO(b'foo contents'))
- request.urlopen(
- 'file:///home/my/dir/baz/baz1.yaml').InAnyOrder().AndReturn(
- six.BytesIO(b'baz1 contents'))
- request.urlopen(
- 'file:///home/my/dir/baz/baz2.yaml').InAnyOrder().AndReturn(
- six.BytesIO(b'baz2 contents'))
- request.urlopen(
- 'file:///home/my/dir/baz/baz3.yaml').InAnyOrder().AndReturn(
- six.BytesIO(b'baz3 contents'))
-
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(self.hot_template),
+ six.BytesIO(b'bar contents'),
+ six.BytesIO(b'foo contents'),
+ six.BytesIO(b'baz1 contents'),
+ six.BytesIO(b'baz2 contents'),
+ six.BytesIO(b'baz3 contents')]
files, tmpl_parsed = template_utils.get_template_contents(
template_file=tmpl_file)
self.assertEqual({
- 'http://localhost/bar.yaml': b'bar contents',
- 'file:///home/my/dir/foo.yaml': b'foo contents',
- 'file:///home/my/dir/baz/baz1.yaml': b'baz1 contents',
- 'file:///home/my/dir/baz/baz2.yaml': b'baz2 contents',
- 'file:///home/my/dir/baz/baz3.yaml': b'baz3 contents',
- }, files)
- self.assertEqual({
'heat_template_version': '2013-05-23',
'resources': {
'resource1': {
@@ -836,9 +793,16 @@ resources:
}
}
}, tmpl_parsed)
-
- def test_hot_template_outputs(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ mock_url.assert_has_calls([
+ mock.call(url),
+ mock.call('http://localhost/bar.yaml'),
+ mock.call('file:///home/my/dir/foo.yaml'),
+ mock.call('file:///home/my/dir/baz/baz1.yaml'),
+ mock.call('file:///home/my/dir/baz/baz2.yaml'),
+ mock.call('file:///home/my/dir/baz/baz3.yaml')
+ ], any_order=True)
+
+ def test_hot_template_outputs(self, mock_url):
tmpl_file = '/home/my/dir/template.yaml'
url = 'file://%s' % tmpl_file
foo_url = 'file:///home/my/dir/foo.yaml'
@@ -848,15 +812,17 @@ outputs:\n\
contents:\n\
value:\n\
get_file: foo.yaml\n'''
- request.urlopen(url).AndReturn(six.BytesIO(contents))
- request.urlopen(foo_url).AndReturn(six.BytesIO(b'foo contents'))
- self.m.ReplayAll()
+ mock_url.side_effect = [six.BytesIO(contents),
+ six.BytesIO(b'foo contents')]
files = template_utils.get_template_contents(
template_file=tmpl_file)[0]
self.assertEqual({foo_url: b'foo contents'}, files)
+ mock_url.assert_has_calls([
+ mock.call(url),
+ mock.call(foo_url)
+ ])
- def test_hot_template_same_file(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ def test_hot_template_same_file(self, mock_url):
tmpl_file = '/home/my/dir/template.yaml'
url = 'file://%s' % tmpl_file
foo_url = 'file:///home/my/dir/foo.yaml'
@@ -869,14 +835,17 @@ outputs:\n\
template:\n\
value:\n\
get_file: foo.yaml\n'''
- request.urlopen(url).AndReturn(six.BytesIO(contents))
+ mock_url.side_effect = [six.BytesIO(contents),
+ six.BytesIO(b'foo contents')]
# asserts that is fetched only once even though it is
# referenced in the template twice
- request.urlopen(foo_url).AndReturn(six.BytesIO(b'foo contents'))
- self.m.ReplayAll()
files = template_utils.get_template_contents(
template_file=tmpl_file)[0]
self.assertEqual({foo_url: b'foo contents'}, files)
+ mock_url.assert_has_calls([
+ mock.call(url),
+ mock.call(foo_url)
+ ])
class TestTemplateTypeFunctions(testtools.TestCase):
@@ -909,38 +878,26 @@ parameters:
type: string
'''
- def setUp(self):
- super(TestTemplateTypeFunctions, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
- def test_hot_template(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_hot_template(self, mock_url):
tmpl_file = '/home/my/dir/template.yaml'
url = 'file:///home/my/dir/template.yaml'
- request.urlopen(
- 'file:///home/my/dir/foo.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(
- 'file:///home/my/dir/foo.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(url).InAnyOrder().AndReturn(
- six.BytesIO(self.hot_template))
- request.urlopen(
- 'file:///home/my/dir/spam/egg.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.egg_template))
- request.urlopen(
- 'file:///home/my/dir/spam/egg.yaml').InAnyOrder().AndReturn(
- six.BytesIO(self.egg_template))
- self.m.ReplayAll()
+
+ def side_effect(args):
+ if url == args:
+ return six.BytesIO(self.hot_template)
+ if 'file:///home/my/dir/foo.yaml' == args:
+ return six.BytesIO(self.foo_template)
+ if 'file:///home/my/dir/spam/egg.yaml' == args:
+ return six.BytesIO(self.egg_template)
+ mock_url.side_effect = side_effect
files, tmpl_parsed = template_utils.get_template_contents(
template_file=tmpl_file)
self.assertEqual(yaml.safe_load(self.foo_template.decode('utf-8')),
json.loads(files.get('file:///home/my/dir/foo.yaml')))
+
self.assertEqual(
yaml.safe_load(self.egg_template.decode('utf-8')),
json.loads(files.get('file:///home/my/dir/spam/egg.yaml')))
@@ -968,6 +925,12 @@ parameters:
}
}, tmpl_parsed)
+ mock_url.assert_has_calls([
+ mock.call('file:///home/my/dir/foo.yaml'),
+ mock.call(url),
+ mock.call('file:///home/my/dir/spam/egg.yaml'),
+ ], any_order=True)
+
class TestTemplateInFileFunctions(testtools.TestCase):
@@ -993,30 +956,21 @@ parameters:
type: string
'''
- def setUp(self):
- super(TestTemplateInFileFunctions, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
- def test_hot_template(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_hot_template(self, mock_url):
tmpl_file = '/home/my/dir/template.yaml'
url = 'file:///home/my/dir/template.yaml'
foo_url = 'file:///home/my/dir/foo.yaml'
bar_url = 'file:///home/my/dir/bar.yaml'
- request.urlopen(url).InAnyOrder().AndReturn(
- six.BytesIO(self.hot_template))
- request.urlopen(foo_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(foo_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(bar_url).InAnyOrder().AndReturn(
- six.BytesIO(self.bar_template))
- request.urlopen(bar_url).InAnyOrder().AndReturn(
- six.BytesIO(self.bar_template))
- self.m.ReplayAll()
+
+ def side_effect(args):
+ if url == args:
+ return six.BytesIO(self.hot_template)
+ if foo_url == args:
+ return six.BytesIO(self.foo_template)
+ if bar_url == args:
+ return six.BytesIO(self.bar_template)
+ mock_url.side_effect = side_effect
files, tmpl_parsed = template_utils.get_template_contents(
template_file=tmpl_file)
@@ -1052,6 +1006,12 @@ parameters:
}
}, tmpl_parsed)
+ mock_url.assert_has_calls([
+ mock.call(foo_url),
+ mock.call(url),
+ mock.call(bar_url),
+ ], any_order=True)
+
class TestNestedIncludes(testtools.TestCase):
@@ -1095,15 +1055,8 @@ parameters:
type: string
'''
- def setUp(self):
- super(TestNestedIncludes, self).setUp()
- self.m = mox.Mox()
-
- self.addCleanup(self.m.VerifyAll)
- self.addCleanup(self.m.UnsetStubs)
-
- def test_env_nested_includes(self):
- self.m.StubOutWithMock(request, 'urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
+ def test_env_nested_includes(self, mock_url):
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = b'''
@@ -1118,35 +1071,24 @@ parameters:
two_url = u'file:///home/my/dir/spam/two.yaml'
three_url = u'file:///home/my/dir/spam/three.yaml'
- request.urlopen(env_url).AndReturn(
- six.BytesIO(env))
- request.urlopen(template_url).AndReturn(
- six.BytesIO(self.hot_template))
- request.urlopen(template_url).AndReturn(
- six.BytesIO(self.hot_template))
-
- request.urlopen(foo_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(egg_url).InAnyOrder().AndReturn(
- six.BytesIO(self.egg_template))
- request.urlopen(ham_url).InAnyOrder().AndReturn(
- six.BytesIO(b'ham contents'))
- request.urlopen(one_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(two_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(three_url).InAnyOrder().AndReturn(
- six.BytesIO(b'three contents'))
- request.urlopen(foo_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(egg_url).InAnyOrder().AndReturn(
- six.BytesIO(self.egg_template))
- request.urlopen(one_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
- request.urlopen(two_url).InAnyOrder().AndReturn(
- six.BytesIO(self.foo_template))
-
- self.m.ReplayAll()
+ def side_effect(args):
+ if env_url == args:
+ return six.BytesIO(env)
+ if template_url == args:
+ return six.BytesIO(self.hot_template)
+ if foo_url == args:
+ return six.BytesIO(self.foo_template)
+ if egg_url == args:
+ return six.BytesIO(self.egg_template)
+ if ham_url == args:
+ return six.BytesIO(b'ham contents')
+ if one_url == args:
+ return six.BytesIO(self.foo_template)
+ if two_url == args:
+ return six.BytesIO(self.foo_template)
+ if three_url == args:
+ return six.BytesIO(b'three contents')
+ mock_url.side_effect = side_effect
files, env_dict = template_utils.process_environment_and_files(
env_file)
@@ -1201,3 +1143,13 @@ parameters:
json.loads(files.get(two_url)))
self.assertEqual(b'three contents',
files.get(three_url))
+ mock_url.assert_has_calls([
+ mock.call(env_url),
+ mock.call(template_url),
+ mock.call(foo_url),
+ mock.call(egg_url),
+ mock.call(ham_url),
+ mock.call(one_url),
+ mock.call(two_url),
+ mock.call(three_url),
+ ], any_order=True)