450 lines
18 KiB
Python
450 lines
18 KiB
Python
# Copyright 2012 OpenStack Foundation
|
|
# All Rights Reserved.
|
|
#
|
|
# 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 os
|
|
|
|
import mock
|
|
import testtools
|
|
|
|
from heatclient.common import utils
|
|
from heatclient import exc
|
|
from heatclient.v1 import resources as hc_res
|
|
|
|
|
|
class ShellTest(testtools.TestCase):
|
|
|
|
def test_format_parameter_none(self):
|
|
self.assertEqual({}, utils.format_parameters(None))
|
|
|
|
def test_format_parameters(self):
|
|
p = utils.format_parameters([
|
|
'InstanceType=m1.large;DBUsername=wp;'
|
|
'DBPassword=verybadpassword;KeyName=heat_key;'
|
|
'LinuxDistribution=F17'])
|
|
self.assertEqual({'InstanceType': 'm1.large',
|
|
'DBUsername': 'wp',
|
|
'DBPassword': 'verybadpassword',
|
|
'KeyName': 'heat_key',
|
|
'LinuxDistribution': 'F17'
|
|
}, p)
|
|
|
|
def test_format_parameters_split(self):
|
|
p = utils.format_parameters([
|
|
'KeyName=heat_key;'
|
|
'DnsSecKey=hsgx1m31PbamNF4WEcHlwjIlCGgifOdoB58/wwC7a4oAONQ/fDV5ct'
|
|
'qrYBoLlKHhTfkyQEw9iVScKYZbbMtMNg==;'
|
|
'UpstreamDNS=8.8.8.8'])
|
|
self.assertEqual({'KeyName': 'heat_key',
|
|
'DnsSecKey': 'hsgx1m31PbamNF4WEcHlwjIlCGgifOdoB58/ww'
|
|
'C7a4oAONQ/fDV5ctqrYBoLlKHhTfkyQEw9iVScKYZbbMtMNg==',
|
|
'UpstreamDNS': '8.8.8.8'}, p)
|
|
|
|
def test_format_parameters_multiple(self):
|
|
p = utils.format_parameters([
|
|
'KeyName=heat_key',
|
|
'DnsSecKey=hsgx1m31PbamNF4WEcHlwjIlCGgifOdoB58/wwC7a4oAONQ/fDV5ct'
|
|
'qrYBoLlKHhTfkyQEw9iVScKYZbbMtMNg==',
|
|
'UpstreamDNS=8.8.8.8'])
|
|
self.assertEqual({'KeyName': 'heat_key',
|
|
'DnsSecKey': 'hsgx1m31PbamNF4WEcHlwjIlCGgifOdoB58/ww'
|
|
'C7a4oAONQ/fDV5ctqrYBoLlKHhTfkyQEw9iVScKYZbbMtMNg==',
|
|
'UpstreamDNS': '8.8.8.8'}, p)
|
|
|
|
def test_format_parameters_multiple_semicolon_values(self):
|
|
p = utils.format_parameters([
|
|
'KeyName=heat_key',
|
|
'DnsSecKey=hsgx1m31;PbaNF4WEcHlwj;IlCGgfOdoB;58/ww7a4oAO;NQ/fD==',
|
|
'UpstreamDNS=8.8.8.8'])
|
|
self.assertEqual({'KeyName': 'heat_key',
|
|
'DnsSecKey': 'hsgx1m31;PbaNF4WEcHlwj;IlCGgfOdoB;58/'
|
|
'ww7a4oAO;NQ/fD==',
|
|
'UpstreamDNS': '8.8.8.8'}, p)
|
|
|
|
def test_format_parameters_parse_semicolon_false(self):
|
|
p = utils.format_parameters(
|
|
['KeyName=heat_key;UpstreamDNS=8.8.8.8;a=b'],
|
|
parse_semicolon=False)
|
|
self.assertEqual({'KeyName': 'heat_key;UpstreamDNS=8.8.8.8;a=b'}, p)
|
|
|
|
def test_format_parameters_multiple_values_per_pamaters(self):
|
|
p = utils.format_parameters([
|
|
'status=COMPLETE',
|
|
'status=FAILED'])
|
|
self.assertIn('status', p)
|
|
self.assertIn('COMPLETE', p['status'])
|
|
self.assertIn('FAILED', p['status'])
|
|
|
|
def test_format_parameter_bad_parameter(self):
|
|
params = ['KeyName=heat_key;UpstreamDNS8.8.8.8']
|
|
ex = self.assertRaises(exc.CommandError,
|
|
utils.format_parameters, params)
|
|
self.assertEqual('Malformed parameter(UpstreamDNS8.8.8.8). '
|
|
'Use the key=value format.', str(ex))
|
|
|
|
def test_format_multiple_bad_parameter(self):
|
|
params = ['KeyName=heat_key', 'UpstreamDNS8.8.8.8']
|
|
ex = self.assertRaises(exc.CommandError,
|
|
utils.format_parameters, params)
|
|
self.assertEqual('Malformed parameter(UpstreamDNS8.8.8.8). '
|
|
'Use the key=value format.', str(ex))
|
|
|
|
def test_link_formatter(self):
|
|
self.assertEqual('', utils.link_formatter(None))
|
|
self.assertEqual('', utils.link_formatter([]))
|
|
self.assertEqual(
|
|
'http://foo.example.com\nhttp://bar.example.com',
|
|
utils.link_formatter([
|
|
{'href': 'http://foo.example.com'},
|
|
{'href': 'http://bar.example.com'}]))
|
|
self.assertEqual(
|
|
'http://foo.example.com (a)\nhttp://bar.example.com (b)',
|
|
utils.link_formatter([
|
|
{'href': 'http://foo.example.com', 'rel': 'a'},
|
|
{'href': 'http://bar.example.com', 'rel': 'b'}]))
|
|
self.assertEqual(
|
|
'\n',
|
|
utils.link_formatter([
|
|
{'hrf': 'http://foo.example.com'},
|
|
{}]))
|
|
|
|
def test_resource_nested_identifier(self):
|
|
rsrc_info = {'resource_name': 'aresource',
|
|
'links': [{'href': u'http://foo/name/id/resources/0',
|
|
'rel': u'self'},
|
|
{'href': u'http://foo/name/id',
|
|
'rel': u'stack'},
|
|
{'href': u'http://foo/n_name/n_id',
|
|
'rel': u'nested'}]}
|
|
rsrc = hc_res.Resource(manager=None, info=rsrc_info)
|
|
self.assertEqual('n_name/n_id', utils.resource_nested_identifier(rsrc))
|
|
|
|
def test_resource_nested_identifier_none(self):
|
|
rsrc_info = {'resource_name': 'aresource',
|
|
'links': [{'href': u'http://foo/name/id/resources/0',
|
|
'rel': u'self'},
|
|
{'href': u'http://foo/name/id',
|
|
'rel': u'stack'}]}
|
|
rsrc = hc_res.Resource(manager=None, info=rsrc_info)
|
|
self.assertIsNone(utils.resource_nested_identifier(rsrc))
|
|
|
|
def test_json_formatter(self):
|
|
self.assertEqual('null', utils.json_formatter(None))
|
|
self.assertEqual('{}', utils.json_formatter({}))
|
|
self.assertEqual('{\n "foo": "bar"\n}',
|
|
utils.json_formatter({"foo": "bar"}))
|
|
self.assertEqual(u'{\n "Uni": "test\u2665"\n}',
|
|
utils.json_formatter({"Uni": u"test\u2665"}))
|
|
|
|
def test_yaml_formatter(self):
|
|
self.assertEqual('null\n...\n', utils.yaml_formatter(None))
|
|
self.assertEqual('{}\n', utils.yaml_formatter({}))
|
|
self.assertEqual('foo: bar\n',
|
|
utils.yaml_formatter({"foo": "bar"}))
|
|
|
|
def test_text_wrap_formatter(self):
|
|
self.assertEqual('', utils.text_wrap_formatter(None))
|
|
self.assertEqual('', utils.text_wrap_formatter(''))
|
|
self.assertEqual('one two three',
|
|
utils.text_wrap_formatter('one two three'))
|
|
self.assertEqual(
|
|
'one two three four five six seven eight nine ten eleven\ntwelve',
|
|
utils.text_wrap_formatter(
|
|
('one two three four five six seven '
|
|
'eight nine ten eleven twelve')))
|
|
|
|
def test_newline_list_formatter(self):
|
|
self.assertEqual('', utils.newline_list_formatter(None))
|
|
self.assertEqual('', utils.newline_list_formatter([]))
|
|
self.assertEqual('one\ntwo',
|
|
utils.newline_list_formatter(['one', 'two']))
|
|
|
|
def test_event_log_formatter(self):
|
|
event1 = {'event_time': '2015-09-28T12:12:12',
|
|
'id': '123456789',
|
|
'resource_name': 'res_name',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'CREATE started'}
|
|
event2 = {'event_time': '2015-09-28T12:12:22',
|
|
'id': '123456789',
|
|
'resource_name': 'res_name',
|
|
'resource_status': 'CREATE_COMPLETE',
|
|
'resource_status_reason': 'CREATE completed'}
|
|
events_list = [hc_res.Resource(manager=None, info=event1),
|
|
hc_res.Resource(manager=None, info=event2)]
|
|
|
|
expected = ('2015-09-28 12:12:12 [res_name]: '
|
|
'CREATE_IN_PROGRESS CREATE started\n'
|
|
'2015-09-28 12:12:22 [res_name]: '
|
|
'CREATE_COMPLETE CREATE completed')
|
|
self.assertEqual(expected, utils.event_log_formatter(events_list))
|
|
self.assertEqual('', utils.event_log_formatter([]))
|
|
|
|
def test_event_log_formatter_resource_path_old_heat(self):
|
|
|
|
events = [{
|
|
'resource_name': 'nested',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested/1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'nested',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'Stack CREATE started',
|
|
'physical_resource_id': '1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
}, {
|
|
'resource_name': 'rg1',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested/1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'rg1',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'state changed',
|
|
'physical_resource_id': None, # note the None from old heat
|
|
'id': '375c49ae-cefb-4fb3-8f4d-1d5f1b9e3e5d'
|
|
}, {
|
|
'resource_name': 'nested-rg1-m4zxcs4pra6t',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested-rg1-m4zxcs4pra6t/'
|
|
'3400bbad-a825-4226-ac23-c607846420db',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'nested-rg1-m4zxcs4pra6t',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'Stack CREATE started',
|
|
'physical_resource_id': '3400bbad-a825-4226-ac23-c607846420db',
|
|
'id': '7e521c84-cd35-4f4c-b0de-962bd3cc40a8'
|
|
}, {
|
|
'resource_name': '1',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested-rg1-m4zxcs4pra6t/'
|
|
'3400bbad-a825-4226-ac23-c607846420db',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': '1',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'state changed',
|
|
'physical_resource_id': None, # note the None from old heat
|
|
'id': 'c6186c16-94ef-4214-a11a-7e3cc8a17f82'
|
|
}]
|
|
|
|
events_list = [hc_res.Resource(manager=None, info=event)
|
|
for event in events]
|
|
|
|
expected = '''\
|
|
2016-09-05 04:10:24Z [nested]: \
|
|
CREATE_IN_PROGRESS Stack CREATE started
|
|
2016-09-05 04:10:24Z [nested.rg1]: \
|
|
CREATE_IN_PROGRESS state changed
|
|
2016-09-05 04:10:24Z [nested-rg1-m4zxcs4pra6t]: \
|
|
CREATE_IN_PROGRESS Stack CREATE started
|
|
2016-09-05 04:10:24Z [nested-rg1-m4zxcs4pra6t.1]: \
|
|
CREATE_IN_PROGRESS state changed'''
|
|
self.assertEqual(expected, utils.event_log_formatter(events_list))
|
|
|
|
def test_event_log_formatter_resource_path(self):
|
|
|
|
events = [{
|
|
'resource_name': 'nested',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested/1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'nested',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'Stack CREATE started',
|
|
'physical_resource_id': '1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
}, {
|
|
'resource_name': 'rg1',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested/1bed5d4d-41d6-4451-b274-c073ebee375d',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'rg1',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'state changed',
|
|
'physical_resource_id': 'nested-rg1-m4zxcs4pra6t',
|
|
'id': '375c49ae-cefb-4fb3-8f4d-1d5f1b9e3e5d'
|
|
}, {
|
|
'resource_name': 'nested-rg1-m4zxcs4pra6t',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested-rg1-m4zxcs4pra6t/'
|
|
'3400bbad-a825-4226-ac23-c607846420db',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': 'nested-rg1-m4zxcs4pra6t',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'Stack CREATE started',
|
|
'physical_resource_id': '3400bbad-a825-4226-ac23-c607846420db',
|
|
'id': '7e521c84-cd35-4f4c-b0de-962bd3cc40a8'
|
|
}, {
|
|
'resource_name': '1',
|
|
'event_time': '2016-09-05T04:10:24Z',
|
|
'links': [{
|
|
'href': 'http://192.0.2.1:8004/v1/t/stacks/'
|
|
'nested-rg1-m4zxcs4pra6t/'
|
|
'3400bbad-a825-4226-ac23-c607846420db',
|
|
'rel': 'stack'
|
|
}],
|
|
'logical_resource_id': '1',
|
|
'resource_status': 'CREATE_IN_PROGRESS',
|
|
'resource_status_reason': 'state changed',
|
|
'physical_resource_id': 'nested-rg1-m4zxcs4pra6t-1-z6sgpq54n6e7',
|
|
'id': 'c6186c16-94ef-4214-a11a-7e3cc8a17f82'
|
|
}]
|
|
|
|
events_list = [hc_res.Resource(manager=None, info=event)
|
|
for event in events]
|
|
|
|
expected = '''\
|
|
2016-09-05 04:10:24Z [nested]: \
|
|
CREATE_IN_PROGRESS Stack CREATE started
|
|
2016-09-05 04:10:24Z [nested.rg1]: \
|
|
CREATE_IN_PROGRESS state changed
|
|
2016-09-05 04:10:24Z [nested.rg1]: \
|
|
CREATE_IN_PROGRESS Stack CREATE started
|
|
2016-09-05 04:10:24Z [nested.rg1.1]: \
|
|
CREATE_IN_PROGRESS state changed'''
|
|
self.assertEqual(expected, utils.event_log_formatter(events_list))
|
|
|
|
|
|
class ShellTestParameterFiles(testtools.TestCase):
|
|
|
|
def test_format_parameter_file_none(self):
|
|
self.assertEqual({}, utils.format_parameter_file(None))
|
|
|
|
def test_format_parameter_file(self):
|
|
tmpl_file = '/opt/stack/template.yaml'
|
|
contents = 'DBUsername=wp\nDBPassword=verybadpassword'
|
|
utils.read_url_content = mock.MagicMock()
|
|
utils.read_url_content.return_value = ('DBUsername=wp\n'
|
|
'DBPassword=verybadpassword')
|
|
|
|
p = utils.format_parameter_file([
|
|
'env_file1=test_file1'], tmpl_file)
|
|
self.assertEqual({'env_file1': contents
|
|
}, p)
|
|
|
|
def test_format_parameter_file_no_template(self):
|
|
tmpl_file = None
|
|
contents = 'DBUsername=wp\nDBPassword=verybadpassword'
|
|
utils.read_url_content = mock.MagicMock()
|
|
utils.read_url_content.return_value = ('DBUsername=wp\n'
|
|
'DBPassword=verybadpassword')
|
|
p = utils.format_parameter_file([
|
|
'env_file1=test_file1'], tmpl_file)
|
|
self.assertEqual({'env_file1': contents
|
|
}, p)
|
|
|
|
def test_format_all_parameters(self):
|
|
tmpl_file = '/opt/stack/template.yaml'
|
|
contents = 'DBUsername=wp\nDBPassword=verybadpassword'
|
|
params = ['KeyName=heat_key;UpstreamDNS=8.8.8.8']
|
|
utils.read_url_content = mock.MagicMock()
|
|
utils.read_url_content.return_value = ('DBUsername=wp\n'
|
|
'DBPassword=verybadpassword')
|
|
p = utils.format_all_parameters(params, [
|
|
'env_file1=test_file1'], template_file=tmpl_file)
|
|
self.assertEqual({'KeyName': 'heat_key',
|
|
'UpstreamDNS': '8.8.8.8',
|
|
'env_file1': contents}, p)
|
|
|
|
|
|
class TestURLFunctions(testtools.TestCase):
|
|
|
|
def setUp(self):
|
|
super(TestURLFunctions, self).setUp()
|
|
self.m = mock.MagicMock()
|
|
|
|
self.addCleanup(self.m.UnsetStubs)
|
|
|
|
def test_normalise_file_path_to_url_relative(self):
|
|
self.assertEqual(
|
|
'file://%s/foo' % os.getcwd(),
|
|
utils.normalise_file_path_to_url(
|
|
'foo'))
|
|
|
|
def test_normalise_file_path_to_url_absolute(self):
|
|
self.assertEqual(
|
|
'file:///tmp/foo',
|
|
utils.normalise_file_path_to_url(
|
|
'/tmp/foo'))
|
|
|
|
def test_normalise_file_path_to_url_file(self):
|
|
self.assertEqual(
|
|
'file:///tmp/foo',
|
|
utils.normalise_file_path_to_url(
|
|
'file:///tmp/foo'))
|
|
|
|
def test_normalise_file_path_to_url_http(self):
|
|
self.assertEqual(
|
|
'http://localhost/foo',
|
|
utils.normalise_file_path_to_url(
|
|
'http://localhost/foo'))
|
|
|
|
def test_get_template_url(self):
|
|
tmpl_file = '/opt/stack/template.yaml'
|
|
tmpl_url = 'file:///opt/stack/template.yaml'
|
|
self.assertEqual(utils.get_template_url(tmpl_file, None),
|
|
tmpl_url)
|
|
self.assertEqual(utils.get_template_url(None, tmpl_url),
|
|
tmpl_url)
|
|
self.assertIsNone(utils.get_template_url(None, None))
|
|
|
|
def test_base_url_for_url(self):
|
|
self.assertEqual(
|
|
'file:///foo/bar',
|
|
utils.base_url_for_url(
|
|
'file:///foo/bar/baz'))
|
|
self.assertEqual(
|
|
'file:///foo/bar',
|
|
utils.base_url_for_url(
|
|
'file:///foo/bar/baz.txt'))
|
|
self.assertEqual(
|
|
'file:///foo/bar',
|
|
utils.base_url_for_url(
|
|
'file:///foo/bar/'))
|
|
self.assertEqual(
|
|
'file:///',
|
|
utils.base_url_for_url(
|
|
'file:///'))
|
|
self.assertEqual(
|
|
'file:///',
|
|
utils.base_url_for_url(
|
|
'file:///foo'))
|
|
|
|
self.assertEqual(
|
|
'http://foo/bar',
|
|
utils.base_url_for_url(
|
|
'http://foo/bar/'))
|
|
self.assertEqual(
|
|
'http://foo/bar',
|
|
utils.base_url_for_url(
|
|
'http://foo/bar/baz.template'))
|