Files
python-heatclient/heatclient/tests/test_template_utils.py
llg8212 9d3d26d903 Remove dependent module py3kcompat
Module py3kcompat was removed from oslo-incubator, we can use
six directly.

* Sync commit of removing py3kcompat from oslo
* use six replace usage of py3kcompat

Change-Id: If0f9397588b2180fe198e804cbbb5b5c8420fe76
Closes-Bug: #1280033
2014-03-18 10:27:55 +08:00

540 lines
18 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from mox3 import mox
import os
import six
from six.moves.urllib import request
import tempfile
import testtools
from testtools.matchers import MatchesRegex
import yaml
from heatclient.common import template_utils
from heatclient import exc
class ShellEnvironmentTest(testtools.TestCase):
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.StringIO(content))
self.m.ReplayAll()
template_utils.resolve_environment_urls(
jenv.get('resource_registry'), files, env_base_url)
if url:
self.assertEqual(files[url], content)
def test_process_environment_file(self):
self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env = '''
resource_registry:
"OS::Thingy": "file:///home/b/a.yaml"
'''
tmpl = '{"foo": "bar"}'
request.urlopen('file://%s' % env_file).AndReturn(
six.StringIO(env))
request.urlopen('file:///home/b/a.yaml').AndReturn(
six.StringIO(tmpl))
self.m.ReplayAll()
files, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual(
{'resource_registry': {
'OS::Thingy': 'file:///home/b/a.yaml'}},
env_dict)
self.assertEqual('{"foo": "bar"}', files['file:///home/b/a.yaml'])
def test_process_environment_relative_file(self):
self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = '''
resource_registry:
"OS::Thingy": a.yaml
'''
tmpl = '{"foo": "bar"}'
request.urlopen(env_url).AndReturn(
six.StringIO(env))
request.urlopen('file:///home/my/dir/a.yaml').AndReturn(
six.StringIO(tmpl))
self.m.ReplayAll()
self.assertEqual(
env_url,
template_utils.normalise_file_path_to_url(env_file))
self.assertEqual(
'file:///home/my/dir',
template_utils.base_url_for_url(env_url))
files, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual(
{'resource_registry': {
'OS::Thingy': 'file:///home/my/dir/a.yaml'}},
env_dict)
self.assertEqual(
'{"foo": "bar"}', files['file:///home/my/dir/a.yaml'])
def test_process_environment_relative_file_up(self):
self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env_url = 'file:///home/my/dir/env.yaml'
env = '''
resource_registry:
"OS::Thingy": ../bar/a.yaml
'''
tmpl = '{"foo": "bar"}'
request.urlopen(env_url).AndReturn(
six.StringIO(env))
request.urlopen('file:///home/my/bar/a.yaml').AndReturn(
six.StringIO(tmpl))
self.m.ReplayAll()
env_url = 'file://%s' % env_file
self.assertEqual(
env_url,
template_utils.normalise_file_path_to_url(env_file))
self.assertEqual(
'file:///home/my/dir',
template_utils.base_url_for_url(env_url))
files, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual(
{'resource_registry': {
'OS::Thingy': 'file:///home/my/bar/a.yaml'}},
env_dict)
self.assertEqual(
'{"foo": "bar"}', files['file:///home/my/bar/a.yaml'])
def test_process_environment_url(self):
env = '''
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'
tmpl = '{"foo": "bar"}'
self.m.StubOutWithMock(request, 'urlopen')
request.urlopen(url).AndReturn(six.StringIO(env))
request.urlopen(tmpl_url).AndReturn(six.StringIO(tmpl))
self.m.ReplayAll()
files, env_dict = template_utils.process_environment_and_files(
url)
self.assertEqual({'resource_registry': {'OS::Thingy': tmpl_url}},
env_dict)
self.assertEqual(tmpl, files[tmpl_url])
def test_process_environment_empty_file(self):
self.m.StubOutWithMock(request, 'urlopen')
env_file = '/home/my/dir/env.yaml'
env = ''
request.urlopen('file://%s' % env_file).AndReturn(six.StringIO(env))
self.m.ReplayAll()
files, env_dict = template_utils.process_environment_and_files(
env_file)
self.assertEqual({}, env_dict)
self.assertEqual({}, files)
def test_no_process_environment_and_files(self):
files, env = template_utils.process_environment_and_files()
self.assertEqual({}, env)
self.assertEqual({}, files)
def test_global_files(self):
a = "A's contents."
url = 'file:///home/b/a.yaml'
env = '''
resource_registry:
"OS::Thingy": "%s"
''' % url
self.collect_links(env, a, url)
def test_nested_files(self):
a = "A's contents."
url = 'file:///home/b/a.yaml'
env = '''
resource_registry:
resources:
freddy:
"OS::Thingy": "%s"
''' % url
self.collect_links(env, a, url)
def test_http_url(self):
a = "A's contents."
url = 'http://no.where/container/a.yaml'
env = '''
resource_registry:
"OS::Thingy": "%s"
''' % url
self.collect_links(env, a, url)
def test_with_base_url(self):
a = "A's contents."
url = 'ftp://no.where/container/a.yaml'
env = '''
resource_registry:
base_url: "ftp://no.where/container/"
resources:
server_for_me:
"OS::Thingy": a.yaml
'''
self.collect_links(env, a, url)
def test_with_built_in_provider(self):
a = "A's contents."
env = '''
resource_registry:
resources:
server_for_me:
"OS::Thingy": OS::Compute::Server
'''
self.collect_links(env, a, None)
def test_with_env_file_base_url_file(self):
a = "A's contents."
url = 'file:///tmp/foo/a.yaml'
env = '''
resource_registry:
resources:
server_for_me:
"OS::Thingy": a.yaml
'''
env_base_url = 'file:///tmp/foo'
self.collect_links(env, a, url, env_base_url)
def test_with_env_file_base_url_http(self):
a = "A's contents."
url = 'http://no.where/path/to/a.yaml'
env = '''
resource_registry:
resources:
server_for_me:
"OS::Thingy": to/a.yaml
'''
env_base_url = 'http://no.where/path'
self.collect_links(env, a, url, env_base_url)
def test_unsupported_protocol(self):
env = '''
resource_registry:
"OS::Thingy": "sftp://no.where/dev/null/a.yaml"
'''
jenv = yaml.safe_load(env)
fields = {'files': {}}
self.assertRaises(exc.CommandError,
template_utils.get_file_contents,
jenv['resource_registry'],
fields)
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",' \
b' "foo": "bar"}'
tmpl_file.write(tmpl)
tmpl_file.flush()
files, tmpl_parsed = template_utils.get_template_contents(
tmpl_file.name)
self.assertEqual({"AWSTemplateFormatVersion": "2010-09-09",
"foo": "bar"}, tmpl_parsed)
self.assertEqual({}, files)
def test_get_template_contents_file_empty(self):
with tempfile.NamedTemporaryFile() as tmpl_file:
ex = self.assertRaises(
exc.CommandError,
template_utils.get_template_contents,
tmpl_file.name)
self.assertEqual(
str(ex),
'Could not fetch template from file://%s' % tmpl_file.name)
def test_get_template_contents_file_none(self):
ex = self.assertRaises(
exc.CommandError,
template_utils.get_template_contents)
self.assertEqual(
str(ex),
('Need to specify exactly one of --template-file, '
'--template-url or --template-object'))
def test_get_template_contents_parse_error(self):
with tempfile.NamedTemporaryFile() as tmpl_file:
tmpl = b'{"foo": "bar"'
tmpl_file.write(tmpl)
tmpl_file.flush()
ex = self.assertRaises(
exc.CommandError,
template_utils.get_template_contents,
tmpl_file.name)
self.assertThat(
str(ex),
MatchesRegex(
'Error parsing template file://%s ' % tmpl_file.name))
def test_get_template_contents_url(self):
tmpl = '{"AWSTemplateFormatVersion" : "2010-09-09", "foo": "bar"}'
url = 'http://no.where/path/to/a.yaml'
self.m.StubOutWithMock(request, 'urlopen')
request.urlopen(url).AndReturn(six.StringIO(tmpl))
self.m.ReplayAll()
files, tmpl_parsed = template_utils.get_template_contents(
template_url=url)
self.assertEqual({"AWSTemplateFormatVersion": "2010-09-09",
"foo": "bar"}, tmpl_parsed)
self.assertEqual({}, files)
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
def object_request(method, object_url):
self.object_requested = True
self.assertEqual('GET', method)
self.assertEqual('http://no.where/path/to/a.yaml', object_url)
return tmpl
files, tmpl_parsed = template_utils.get_template_contents(
template_object=url,
object_request=object_request)
self.assertEqual({"AWSTemplateFormatVersion": "2010-09-09",
"foo": "bar"}, tmpl_parsed)
self.assertEqual({}, files)
self.assertTrue(self.object_requested)
class TestTemplateGetFileFunctions(testtools.TestCase):
hot_template = '''heat_template_version: 2013-05-23
resources:
resource1:
type: type1
properties:
foo: {get_file: foo.yaml}
bar:
get_file:
'http://localhost/bar.yaml'
resource2:
type: type1
properties:
baz:
- {get_file: baz/baz1.yaml}
- {get_file: baz/baz2.yaml}
- {get_file: baz/baz3.yaml}
ignored_list: {get_file: [ignore, me]}
ignored_dict: {get_file: {ignore: me}}
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')
tmpl_file = '/home/my/dir/template.yaml'
url = 'file:///home/my/dir/template.yaml'
request.urlopen(url).AndReturn(
six.StringIO(self.hot_template))
request.urlopen(
'http://localhost/bar.yaml').InAnyOrder().AndReturn(
six.StringIO('bar contents'))
request.urlopen(
'file:///home/my/dir/foo.yaml').InAnyOrder().AndReturn(
six.StringIO('foo contents'))
request.urlopen(
'file:///home/my/dir/baz/baz1.yaml').InAnyOrder().AndReturn(
six.StringIO('baz1 contents'))
request.urlopen(
'file:///home/my/dir/baz/baz2.yaml').InAnyOrder().AndReturn(
six.StringIO('baz2 contents'))
request.urlopen(
'file:///home/my/dir/baz/baz3.yaml').InAnyOrder().AndReturn(
six.StringIO('baz3 contents'))
self.m.ReplayAll()
files, tmpl_parsed = template_utils.get_template_contents(
template_file=tmpl_file)
self.assertEqual({
'http://localhost/bar.yaml': 'bar contents',
'file:///home/my/dir/foo.yaml': 'foo contents',
'file:///home/my/dir/baz/baz1.yaml': 'baz1 contents',
'file:///home/my/dir/baz/baz2.yaml': 'baz2 contents',
'file:///home/my/dir/baz/baz3.yaml': 'baz3 contents',
}, files)
self.assertEqual({
'heat_template_version': '2013-05-23',
'resources': {
'resource1': {
'type': 'type1',
'properties': {
'bar': {'get_file': 'http://localhost/bar.yaml'},
'foo': {'get_file': 'file:///home/my/dir/foo.yaml'},
},
},
'resource2': {
'type': 'type1',
'properties': {
'baz': [
{'get_file': 'file:///home/my/dir/baz/baz1.yaml'},
{'get_file': 'file:///home/my/dir/baz/baz2.yaml'},
{'get_file': 'file:///home/my/dir/baz/baz3.yaml'},
],
'ignored_list': {'get_file': ['ignore', 'me']},
'ignored_dict': {'get_file': {'ignore': 'me'}},
'ignored_none': {'get_file': None},
},
}
}
}, tmpl_parsed)
self.m.VerifyAll()
def test_hot_template_outputs(self):
self.m.StubOutWithMock(request, 'urlopen')
tmpl_file = '/home/my/dir/template.yaml'
url = 'file://%s' % tmpl_file
contents = str('heat_template_version: 2013-05-23\n'
'outputs:\n'
' contents:\n'
' value:\n'
' get_file: template.yaml\n')
request.urlopen(url).AndReturn(six.StringIO(contents))
request.urlopen(url).AndReturn(six.StringIO(contents))
self.m.ReplayAll()
files, tmpl_parsed = template_utils.get_template_contents(
template_file=tmpl_file)
self.assertEqual({url: contents}, files)
self.m.VerifyAll()
class TestURLFunctions(testtools.TestCase):
def setUp(self):
super(TestURLFunctions, self).setUp()
self.m = mox.Mox()
self.addCleanup(self.m.VerifyAll)
self.addCleanup(self.m.UnsetStubs)
def test_normalise_file_path_to_url_relative(self):
self.assertEqual(
'file://%s/foo' % os.getcwd(),
template_utils.normalise_file_path_to_url(
'foo'))
def test_normalise_file_path_to_url_absolute(self):
self.assertEqual(
'file:///tmp/foo',
template_utils.normalise_file_path_to_url(
'/tmp/foo'))
def test_normalise_file_path_to_url_file(self):
self.assertEqual(
'file:///tmp/foo',
template_utils.normalise_file_path_to_url(
'file:///tmp/foo'))
def test_normalise_file_path_to_url_http(self):
self.assertEqual(
'http://localhost/foo',
template_utils.normalise_file_path_to_url(
'http://localhost/foo'))
def test_base_url_for_url(self):
self.assertEqual(
'file:///foo/bar',
template_utils.base_url_for_url(
'file:///foo/bar/baz'))
self.assertEqual(
'file:///foo/bar',
template_utils.base_url_for_url(
'file:///foo/bar/baz.txt'))
self.assertEqual(
'file:///foo/bar',
template_utils.base_url_for_url(
'file:///foo/bar/'))
self.assertEqual(
'file:///',
template_utils.base_url_for_url(
'file:///'))
self.assertEqual(
'file:///',
template_utils.base_url_for_url(
'file:///foo'))
self.assertEqual(
'http://foo/bar',
template_utils.base_url_for_url(
'http://foo/bar/'))
self.assertEqual(
'http://foo/bar',
template_utils.base_url_for_url(
'http://foo/bar/baz.template'))