1203 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1203 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| #    http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | |
| # implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| 
 | |
| import base64
 | |
| import json
 | |
| from mox3 import mox
 | |
| import six
 | |
| from six.moves.urllib import error
 | |
| from six.moves.urllib import request
 | |
| import tempfile
 | |
| import testtools
 | |
| from testtools import matchers
 | |
| import yaml
 | |
| 
 | |
| from heatclient.common import template_utils
 | |
| from heatclient.common import utils
 | |
| from heatclient import exc
 | |
| 
 | |
| 
 | |
| 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 test_ignore_env_keys(self):
 | |
|         self.m.StubOutWithMock(request, 'urlopen')
 | |
|         env_file = '/home/my/dir/env.yaml'
 | |
|         env = b'''
 | |
|         resource_registry:
 | |
|           resources:
 | |
|             bar:
 | |
|               hooks: pre_create
 | |
|               restricted_actions: replace
 | |
|         '''
 | |
|         request.urlopen('file://%s' % env_file).AndReturn(
 | |
|             six.BytesIO(env))
 | |
|         self.m.ReplayAll()
 | |
|         _, env_dict = template_utils.process_environment_and_files(
 | |
|             env_file)
 | |
|         self.assertEqual(
 | |
|             {u'resource_registry': {u'resources': {
 | |
|                 u'bar': {u'hooks': u'pre_create',
 | |
|                          u'restricted_actions': u'replace'}}}},
 | |
|             env_dict)
 | |
|         self.m.VerifyAll()
 | |
| 
 | |
|     def test_process_environment_file(self):
 | |
| 
 | |
|         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()
 | |
| 
 | |
|         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(self.template_a.decode('utf-8'),
 | |
|                          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 = 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()
 | |
| 
 | |
|         self.assertEqual(
 | |
|             env_url,
 | |
|             utils.normalise_file_path_to_url(env_file))
 | |
|         self.assertEqual(
 | |
|             'file:///home/my/dir',
 | |
|             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(self.template_a.decode('utf-8'),
 | |
|                          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 = 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()
 | |
| 
 | |
|         env_url = 'file://%s' % env_file
 | |
|         self.assertEqual(
 | |
|             env_url,
 | |
|             utils.normalise_file_path_to_url(env_file))
 | |
|         self.assertEqual(
 | |
|             'file:///home/my/dir',
 | |
|             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(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/my/bar/a.yaml'])
 | |
| 
 | |
|     def test_process_environment_url(self):
 | |
|         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()
 | |
| 
 | |
|         files, env_dict = template_utils.process_environment_and_files(
 | |
|             url)
 | |
| 
 | |
|         self.assertEqual({'resource_registry': {'OS::Thingy': tmpl_url}},
 | |
|                          env_dict)
 | |
|         self.assertEqual(self.template_a.decode('utf-8'), files[tmpl_url])
 | |
| 
 | |
|     def test_process_environment_empty_file(self):
 | |
| 
 | |
|         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()
 | |
| 
 | |
|         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_process_multiple_environments_and_files(self):
 | |
| 
 | |
|         self.m.StubOutWithMock(request, 'urlopen')
 | |
|         env_file1 = '/home/my/dir/env1.yaml'
 | |
|         env_file2 = '/home/my/dir/env2.yaml'
 | |
| 
 | |
|         env1 = b'''
 | |
|         parameters:
 | |
|           "param1": "value1"
 | |
|         resource_registry:
 | |
|           "OS::Thingy1": "file:///home/b/a.yaml"
 | |
|         '''
 | |
|         env2 = b'''
 | |
|         parameters:
 | |
|           "param2": "value2"
 | |
|         resource_registry:
 | |
|           "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()
 | |
| 
 | |
|         files, env = template_utils.process_multiple_environments_and_files(
 | |
|             [env_file1, env_file2])
 | |
|         self.assertEqual(
 | |
|             {
 | |
|                 'resource_registry': {
 | |
|                     'OS::Thingy1': 'file:///home/b/a.yaml',
 | |
|                     'OS::Thingy2': 'file:///home/b/b.yaml'},
 | |
|                 'parameters': {
 | |
|                     'param1': 'value1',
 | |
|                     'param2': 'value2'}
 | |
|             },
 | |
|             env)
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/b/a.yaml'])
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/b/b.yaml'])
 | |
| 
 | |
|     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'
 | |
| 
 | |
|         env1 = b'''
 | |
|         resource_registry:
 | |
|           resources:
 | |
|             resource1:
 | |
|               "OS::Thingy1": "file:///home/b/a.yaml"
 | |
|             resource2:
 | |
|               "OS::Thingy2": "file:///home/b/b.yaml"
 | |
|         '''
 | |
|         env2 = b'''
 | |
|         resource_registry:
 | |
|           resources:
 | |
|             resource1:
 | |
|               "OS::Thingy3": "file:///home/b/a.yaml"
 | |
|             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()
 | |
| 
 | |
|         files, env = template_utils.process_multiple_environments_and_files(
 | |
|             [env_file1, env_file2])
 | |
|         self.assertEqual(
 | |
|             {
 | |
|                 'resource_registry': {
 | |
|                     'resources': {
 | |
|                         'resource1': {
 | |
|                             'OS::Thingy1': 'file:///home/b/a.yaml',
 | |
|                             'OS::Thingy3': 'file:///home/b/a.yaml'
 | |
|                         },
 | |
|                         'resource2': {
 | |
|                             'OS::Thingy2': 'file:///home/b/b.yaml',
 | |
|                             'OS::Thingy4': 'file:///home/b/b.yaml'
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             },
 | |
|             env)
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/b/a.yaml'])
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/b/b.yaml'])
 | |
| 
 | |
|     def test_no_process_multiple_environments_and_files(self):
 | |
|         files, env = template_utils.process_multiple_environments_and_files()
 | |
|         self.assertEqual({}, env)
 | |
|         self.assertEqual({}, files)
 | |
| 
 | |
|     def test_process_multiple_environments_and_files_from_object(self):
 | |
| 
 | |
|         env_object = 'http://no.where/path/to/env.yaml'
 | |
|         env1 = b'''
 | |
|         parameters:
 | |
|           "param1": "value1"
 | |
|         resource_registry:
 | |
|           "OS::Thingy1": "b/a.yaml"
 | |
|         '''
 | |
| 
 | |
|         self.m.ReplayAll()
 | |
| 
 | |
|         self.object_requested = False
 | |
| 
 | |
|         def env_path_is_object(object_url):
 | |
|             return True
 | |
| 
 | |
|         def object_request(method, object_url):
 | |
|             self.object_requested = True
 | |
|             self.assertEqual('GET', method)
 | |
|             self.assertTrue(object_url.startswith("http://no.where/path/to/"))
 | |
|             if object_url == env_object:
 | |
|                 return env1
 | |
|             else:
 | |
|                 return self.template_a
 | |
| 
 | |
|         files, env = template_utils.process_multiple_environments_and_files(
 | |
|             env_paths=[env_object], env_path_is_object=env_path_is_object,
 | |
|             object_request=object_request)
 | |
|         self.assertEqual(
 | |
|             {
 | |
|                 'resource_registry': {
 | |
|                     'OS::Thingy1': 'http://no.where/path/to/b/a.yaml'},
 | |
|                 'parameters': {'param1': 'value1'}
 | |
|             },
 | |
|             env)
 | |
|         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):
 | |
|         # Setup
 | |
|         self.m.StubOutWithMock(request, 'urlopen')
 | |
|         env_file1 = '/home/my/dir/env1.yaml'
 | |
| 
 | |
|         env1 = b'''
 | |
|         parameters:
 | |
|           "param1": "value1"
 | |
|         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()
 | |
| 
 | |
|         # Test
 | |
|         env_file_list = []
 | |
|         files, env = template_utils.process_multiple_environments_and_files(
 | |
|             [env_file1], env_list_tracker=env_file_list)
 | |
| 
 | |
|         # Verify
 | |
|         expected_env = {'parameters': {'param1': 'value1'},
 | |
|                         'resource_registry':
 | |
|                             {'OS::Thingy1': 'file:///home/b/a.yaml'}
 | |
|                         }
 | |
|         self.assertEqual(expected_env, env)
 | |
| 
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/b/a.yaml'])
 | |
| 
 | |
|         self.assertEqual(['file:///home/my/dir/env1.yaml'], env_file_list)
 | |
|         self.assertTrue('file:///home/my/dir/env1.yaml' in files)
 | |
|         self.assertEqual(expected_env,
 | |
|                          json.loads(files['file:///home/my/dir/env1.yaml']))
 | |
| 
 | |
|     def test_process_environment_relative_file_tracker(self):
 | |
| 
 | |
|         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()
 | |
| 
 | |
|         self.assertEqual(
 | |
|             env_url,
 | |
|             utils.normalise_file_path_to_url(env_file))
 | |
|         self.assertEqual(
 | |
|             'file:///home/my/dir',
 | |
|             utils.base_url_for_url(env_url))
 | |
| 
 | |
|         env_file_list = []
 | |
|         files, env = template_utils.process_multiple_environments_and_files(
 | |
|             [env_file], env_list_tracker=env_file_list)
 | |
| 
 | |
|         # Verify
 | |
|         expected_env = {'resource_registry':
 | |
|                         {'OS::Thingy': 'file:///home/my/dir/a.yaml'}}
 | |
|         self.assertEqual(expected_env, env)
 | |
| 
 | |
|         self.assertEqual(self.template_a.decode('utf-8'),
 | |
|                          files['file:///home/my/dir/a.yaml'])
 | |
|         self.assertEqual(['file:///home/my/dir/env.yaml'], env_file_list)
 | |
|         self.assertEqual(json.dumps(expected_env),
 | |
|                          files['file:///home/my/dir/env.yaml'])
 | |
| 
 | |
|     def test_global_files(self):
 | |
|         url = 'file:///home/b/a.yaml'
 | |
|         env = '''
 | |
|         resource_registry:
 | |
|           "OS::Thingy": "%s"
 | |
|         ''' % url
 | |
|         self.collect_links(env, self.template_a, url)
 | |
| 
 | |
|     def test_nested_files(self):
 | |
|         url = 'file:///home/b/a.yaml'
 | |
|         env = '''
 | |
|         resource_registry:
 | |
|           resources:
 | |
|             freddy:
 | |
|               "OS::Thingy": "%s"
 | |
|         ''' % url
 | |
|         self.collect_links(env, self.template_a, url)
 | |
| 
 | |
|     def test_http_url(self):
 | |
|         url = 'http://no.where/container/a.yaml'
 | |
|         env = '''
 | |
|         resource_registry:
 | |
|           "OS::Thingy": "%s"
 | |
|         ''' % url
 | |
|         self.collect_links(env, self.template_a, url)
 | |
| 
 | |
|     def test_with_base_url(self):
 | |
|         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, self.template_a, url)
 | |
| 
 | |
|     def test_with_built_in_provider(self):
 | |
|         env = '''
 | |
|         resource_registry:
 | |
|           resources:
 | |
|             server_for_me:
 | |
|               "OS::Thingy": OS::Compute::Server
 | |
|         '''
 | |
|         self.collect_links(env, self.template_a, None)
 | |
| 
 | |
|     def test_with_env_file_base_url_file(self):
 | |
|         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, self.template_a, url, env_base_url)
 | |
| 
 | |
|     def test_with_env_file_base_url_http(self):
 | |
|         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, self.template_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(
 | |
|                 'Could not fetch template from file://%s' % tmpl_file.name,
 | |
|                 str(ex))
 | |
| 
 | |
|     def test_get_template_file_nonextant(self):
 | |
|         nonextant_file = '/template/dummy/file/path/and/name.yaml'
 | |
|         ex = self.assertRaises(
 | |
|             error.URLError,
 | |
|             template_utils.get_template_contents,
 | |
|             nonextant_file)
 | |
|         self.assertEqual(
 | |
|             "<urlopen error [Errno 2] No such file or directory: '%s'>"
 | |
|             % nonextant_file,
 | |
|             str(ex))
 | |
| 
 | |
|     def test_get_template_contents_file_none(self):
 | |
|         ex = self.assertRaises(
 | |
|             exc.CommandError,
 | |
|             template_utils.get_template_contents)
 | |
|         self.assertEqual(
 | |
|             ('Need to specify exactly one of --template-file, '
 | |
|              '--template-url or --template-object'),
 | |
|             str(ex))
 | |
| 
 | |
|     def test_get_template_contents_file_none_existing(self):
 | |
|         files, tmpl_parsed = template_utils.get_template_contents(
 | |
|             existing=True)
 | |
|         self.assertIsNone(tmpl_parsed)
 | |
|         self.assertEqual({}, files)
 | |
| 
 | |
|     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),
 | |
|                 matchers.MatchesRegex(
 | |
|                     'Error parsing template file://%s ' % tmpl_file.name))
 | |
| 
 | |
|     def test_get_template_contents_url(self):
 | |
|         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()
 | |
| 
 | |
|         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)
 | |
| 
 | |
|     def test_get_nested_stack_template_contents_object(self):
 | |
|         tmpl = ('{"heat_template_version": "2016-04-08",'
 | |
|                 '"resources": {'
 | |
|                 '"FooBar": {'
 | |
|                 '"type": "foo/bar.yaml"}}}')
 | |
|         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.assertTrue(object_url.startswith("http://no.where/path/to/"))
 | |
|             if object_url == url:
 | |
|                 return tmpl
 | |
|             else:
 | |
|                 return '{"heat_template_version": "2016-04-08"}'
 | |
| 
 | |
|         files, tmpl_parsed = template_utils.get_template_contents(
 | |
|             template_object=url,
 | |
|             object_request=object_request)
 | |
| 
 | |
|         self.assertEqual(files['http://no.where/path/to/foo/bar.yaml'],
 | |
|                          '{"heat_template_version": "2016-04-08"}')
 | |
|         self.assertTrue(self.object_requested)
 | |
| 
 | |
|     def check_non_utf8_content(self, filename, content):
 | |
|         base_url = 'file:///tmp'
 | |
|         url = '%s/%s' % (base_url, filename)
 | |
|         template = {'resources':
 | |
|                     {'one_init':
 | |
|                      {'type': 'OS::Heat::CloudConfig',
 | |
|                       'properties':
 | |
|                       {'cloud_config':
 | |
|                        {'write_files':
 | |
|                         [{'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)
 | |
| 
 | |
|     def test_get_zip_content(self):
 | |
|         filename = 'heat.zip'
 | |
|         content = b'''\
 | |
| UEsDBAoAAAAAAEZZWkRbOAuBBQAAAAUAAAAIABwAaGVhdC50eHRVVAkAAxRbDVNYh\
 | |
| t9SdXgLAAEE\n6AMAAATpAwAAaGVhdApQSwECHgMKAAAAAABGWVpEWzgLgQUAAAAF\
 | |
| AAAACAAYAAAAAAABAAAApIEA\nAAAAaGVhdC50eHRVVAUAAxRbDVN1eAsAAQToAwA\
 | |
| ABOkDAABQSwUGAAAAAAEAAQBOAAAARwAAAAAA\n'''
 | |
|         # zip has '\0' in stream
 | |
|         self.assertIn(b'\0', base64.decodestring(content))
 | |
|         decoded_content = base64.decodestring(content)
 | |
|         if six.PY3:
 | |
|             self.assertRaises(UnicodeDecodeError, decoded_content.decode)
 | |
|         else:
 | |
|             self.assertRaises(
 | |
|                 UnicodeDecodeError,
 | |
|                 json.dumps,
 | |
|                 {'content': decoded_content})
 | |
|         self.check_non_utf8_content(
 | |
|             filename=filename, content=content)
 | |
| 
 | |
|     def test_get_utf16_content(self):
 | |
|         filename = 'heat.utf16'
 | |
|         content = b'//4tTkhTCgA=\n'
 | |
|         # utf6 has '\0' in stream
 | |
|         self.assertIn(b'\0', base64.decodestring(content))
 | |
|         decoded_content = base64.decodestring(content)
 | |
|         if six.PY3:
 | |
|             self.assertRaises(UnicodeDecodeError, decoded_content.decode)
 | |
|         else:
 | |
|             self.assertRaises(
 | |
|                 UnicodeDecodeError,
 | |
|                 json.dumps,
 | |
|                 {'content': decoded_content})
 | |
|         self.check_non_utf8_content(filename=filename, content=content)
 | |
| 
 | |
|     def test_get_gb18030_content(self):
 | |
|         filename = 'heat.gb18030'
 | |
|         content = b'1tDO5wo=\n'
 | |
|         # gb18030 has no '\0' in stream
 | |
|         self.assertNotIn('\0', base64.decodestring(content))
 | |
|         decoded_content = base64.decodestring(content)
 | |
|         if six.PY3:
 | |
|             self.assertRaises(UnicodeDecodeError, decoded_content.decode)
 | |
|         else:
 | |
|             self.assertRaises(
 | |
|                 UnicodeDecodeError,
 | |
|                 json.dumps,
 | |
|                 {'content': decoded_content})
 | |
|         self.check_non_utf8_content(filename=filename, content=content)
 | |
| 
 | |
| 
 | |
| class TestTemplateGetFileFunctions(testtools.TestCase):
 | |
| 
 | |
|     hot_template = b'''heat_template_version: 2013-05-23
 | |
| resources:
 | |
|   resource1:
 | |
|     type: OS::type1
 | |
|     properties:
 | |
|       foo: {get_file: foo.yaml}
 | |
|       bar:
 | |
|         get_file:
 | |
|           'http://localhost/bar.yaml'
 | |
|   resource2:
 | |
|     type: OS::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.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()
 | |
| 
 | |
|         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': {
 | |
|                     'type': 'OS::type1',
 | |
|                     'properties': {
 | |
|                         'bar': {'get_file': 'http://localhost/bar.yaml'},
 | |
|                         'foo': {'get_file': 'file:///home/my/dir/foo.yaml'},
 | |
|                     },
 | |
|                 },
 | |
|                 'resource2': {
 | |
|                     'type': 'OS::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)
 | |
| 
 | |
|     def test_hot_template_outputs(self):
 | |
|         self.m.StubOutWithMock(request, 'urlopen')
 | |
|         tmpl_file = '/home/my/dir/template.yaml'
 | |
|         url = 'file://%s' % tmpl_file
 | |
|         foo_url = 'file:///home/my/dir/foo.yaml'
 | |
|         contents = b'''
 | |
| heat_template_version: 2013-05-23\n\
 | |
| 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()
 | |
|         files = template_utils.get_template_contents(
 | |
|             template_file=tmpl_file)[0]
 | |
|         self.assertEqual({foo_url: b'foo contents'}, files)
 | |
| 
 | |
|     def test_hot_template_same_file(self):
 | |
|         self.m.StubOutWithMock(request, 'urlopen')
 | |
|         tmpl_file = '/home/my/dir/template.yaml'
 | |
|         url = 'file://%s' % tmpl_file
 | |
|         foo_url = 'file:///home/my/dir/foo.yaml'
 | |
|         contents = b'''
 | |
| heat_template_version: 2013-05-23\n
 | |
| outputs:\n\
 | |
|   contents:\n\
 | |
|     value:\n\
 | |
|       get_file: foo.yaml\n\
 | |
|   template:\n\
 | |
|     value:\n\
 | |
|       get_file: foo.yaml\n'''
 | |
|         request.urlopen(url).AndReturn(six.BytesIO(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)
 | |
| 
 | |
| 
 | |
| class TestTemplateTypeFunctions(testtools.TestCase):
 | |
| 
 | |
|     hot_template = b'''heat_template_version: 2013-05-23
 | |
| parameters:
 | |
|   param1:
 | |
|     type: string
 | |
| resources:
 | |
|   resource1:
 | |
|     type: foo.yaml
 | |
|     properties:
 | |
|       foo: bar
 | |
|   resource2:
 | |
|     type: OS::Heat::ResourceGroup
 | |
|     properties:
 | |
|       resource_def:
 | |
|         type: spam/egg.yaml
 | |
|     '''
 | |
| 
 | |
|     foo_template = b'''heat_template_version: "2013-05-23"
 | |
| parameters:
 | |
|   foo:
 | |
|     type: string
 | |
|     '''
 | |
| 
 | |
|     egg_template = b'''heat_template_version: "2013-05-23"
 | |
| parameters:
 | |
|   egg:
 | |
|     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')
 | |
|         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()
 | |
| 
 | |
|         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')))
 | |
| 
 | |
|         self.assertEqual({
 | |
|             u'heat_template_version': u'2013-05-23',
 | |
|             u'parameters': {
 | |
|                 u'param1': {
 | |
|                     u'type': u'string'
 | |
|                 }
 | |
|             },
 | |
|             u'resources': {
 | |
|                 u'resource1': {
 | |
|                     u'type': u'file:///home/my/dir/foo.yaml',
 | |
|                     u'properties': {u'foo': u'bar'}
 | |
|                 },
 | |
|                 u'resource2': {
 | |
|                     u'type': u'OS::Heat::ResourceGroup',
 | |
|                     u'properties': {
 | |
|                         u'resource_def': {
 | |
|                             u'type': u'file:///home/my/dir/spam/egg.yaml'
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }, tmpl_parsed)
 | |
| 
 | |
| 
 | |
| class TestTemplateInFileFunctions(testtools.TestCase):
 | |
| 
 | |
|     hot_template = b'''heat_template_version: 2013-05-23
 | |
| resources:
 | |
|   resource1:
 | |
|     type: OS::Heat::Stack
 | |
|     properties:
 | |
|       template: {get_file: foo.yaml}
 | |
|     '''
 | |
| 
 | |
|     foo_template = b'''heat_template_version: "2013-05-23"
 | |
| resources:
 | |
|   foo:
 | |
|     type: OS::Type1
 | |
|     properties:
 | |
|       config: {get_file: bar.yaml}
 | |
|     '''
 | |
| 
 | |
|     bar_template = b'''heat_template_version: "2013-05-23"
 | |
| parameters:
 | |
|   bar:
 | |
|     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')
 | |
|         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()
 | |
| 
 | |
|         files, tmpl_parsed = template_utils.get_template_contents(
 | |
|             template_file=tmpl_file)
 | |
| 
 | |
|         self.assertEqual(yaml.safe_load(self.bar_template.decode('utf-8')),
 | |
|                          json.loads(files.get('file:///home/my/dir/bar.yaml')))
 | |
| 
 | |
|         self.assertEqual({
 | |
|             u'heat_template_version': u'2013-05-23',
 | |
|             u'resources': {
 | |
|                 u'foo': {
 | |
|                     u'type': u'OS::Type1',
 | |
|                     u'properties': {
 | |
|                         u'config': {
 | |
|                             u'get_file': u'file:///home/my/dir/bar.yaml'
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }, json.loads(files.get('file:///home/my/dir/foo.yaml')))
 | |
| 
 | |
|         self.assertEqual({
 | |
|             u'heat_template_version': u'2013-05-23',
 | |
|             u'resources': {
 | |
|                 u'resource1': {
 | |
|                     u'type': u'OS::Heat::Stack',
 | |
|                     u'properties': {
 | |
|                         u'template': {
 | |
|                             u'get_file': u'file:///home/my/dir/foo.yaml'
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }, tmpl_parsed)
 | |
| 
 | |
| 
 | |
| class TestNestedIncludes(testtools.TestCase):
 | |
| 
 | |
|     hot_template = b'''heat_template_version: 2013-05-23
 | |
| parameters:
 | |
|   param1:
 | |
|     type: string
 | |
| resources:
 | |
|   resource1:
 | |
|     type: foo.yaml
 | |
|     properties:
 | |
|       foo: bar
 | |
|   resource2:
 | |
|     type: OS::Heat::ResourceGroup
 | |
|     properties:
 | |
|       resource_def:
 | |
|         type: spam/egg.yaml
 | |
|       with: {get_file: spam/ham.yaml}
 | |
|     '''
 | |
| 
 | |
|     egg_template = b'''heat_template_version: 2013-05-23
 | |
| parameters:
 | |
|   param1:
 | |
|     type: string
 | |
| resources:
 | |
|   resource1:
 | |
|     type: one.yaml
 | |
|     properties:
 | |
|       foo: bar
 | |
|   resource2:
 | |
|     type: OS::Heat::ResourceGroup
 | |
|     properties:
 | |
|       resource_def:
 | |
|         type: two.yaml
 | |
|       with: {get_file: three.yaml}
 | |
|     '''
 | |
| 
 | |
|     foo_template = b'''heat_template_version: "2013-05-23"
 | |
| parameters:
 | |
|   foo:
 | |
|     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')
 | |
|         env_file = '/home/my/dir/env.yaml'
 | |
|         env_url = 'file:///home/my/dir/env.yaml'
 | |
|         env = b'''
 | |
|         resource_registry:
 | |
|           "OS::Thingy": template.yaml
 | |
|         '''
 | |
|         template_url = u'file:///home/my/dir/template.yaml'
 | |
|         foo_url = u'file:///home/my/dir/foo.yaml'
 | |
|         egg_url = u'file:///home/my/dir/spam/egg.yaml'
 | |
|         ham_url = u'file:///home/my/dir/spam/ham.yaml'
 | |
|         one_url = u'file:///home/my/dir/spam/one.yaml'
 | |
|         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()
 | |
| 
 | |
|         files, env_dict = template_utils.process_environment_and_files(
 | |
|             env_file)
 | |
| 
 | |
|         self.assertEqual(
 | |
|             {'resource_registry': {
 | |
|                 'OS::Thingy': template_url}},
 | |
|             env_dict)
 | |
| 
 | |
|         self.assertEqual({
 | |
|             u'heat_template_version': u'2013-05-23',
 | |
|             u'parameters': {u'param1': {u'type': u'string'}},
 | |
|             u'resources': {
 | |
|                 u'resource1': {
 | |
|                     u'properties': {u'foo': u'bar'},
 | |
|                     u'type': foo_url
 | |
|                 },
 | |
|                 u'resource2': {
 | |
|                     u'type': u'OS::Heat::ResourceGroup',
 | |
|                     u'properties': {
 | |
|                         u'resource_def': {
 | |
|                             u'type': egg_url},
 | |
|                         u'with': {u'get_file': ham_url}
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }, json.loads(files.get(template_url)))
 | |
| 
 | |
|         self.assertEqual(yaml.safe_load(self.foo_template.decode('utf-8')),
 | |
|                          json.loads(files.get(foo_url)))
 | |
|         self.assertEqual({
 | |
|             u'heat_template_version': u'2013-05-23',
 | |
|             u'parameters': {u'param1': {u'type': u'string'}},
 | |
|             u'resources': {
 | |
|                 u'resource1': {
 | |
|                     u'properties': {u'foo': u'bar'},
 | |
|                     u'type': one_url},
 | |
|                 u'resource2': {
 | |
|                     u'type': u'OS::Heat::ResourceGroup',
 | |
|                     u'properties': {
 | |
|                         u'resource_def': {u'type': two_url},
 | |
|                         u'with': {u'get_file': three_url}
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }, json.loads(files.get(egg_url)))
 | |
|         self.assertEqual(b'ham contents',
 | |
|                          files.get(ham_url))
 | |
|         self.assertEqual(yaml.safe_load(self.foo_template.decode('utf-8')),
 | |
|                          json.loads(files.get(one_url)))
 | |
|         self.assertEqual(yaml.safe_load(self.foo_template.decode('utf-8')),
 | |
|                          json.loads(files.get(two_url)))
 | |
|         self.assertEqual(b'three contents',
 | |
|                          files.get(three_url))
 | 
