From a8af89ec9733039ec43cdad1af0821feea93499c Mon Sep 17 00:00:00 2001 From: huangtianhua Date: Mon, 18 Sep 2017 15:59:21 +0800 Subject: [PATCH] Make sure we can get watch server url in uwsgi mode We get the 'watch' server url by translating the 'cfn' server url if the 'watch' server url is not configurated, but in uwsgi mode, the code logic is incorrect, this patch changes the logic to make sure that we can get the watch server url in both modes. Change-Id: Iebf2480f97c11474412d74726eba9cf5c8ed2193 Closes-Bug: #1716815 --- heat/engine/clients/os/heat_plugin.py | 24 ++++++++++++++++++------ heat/tests/clients/test_clients.py | 15 ++++++++++++--- heat/tests/openstack/nova/test_server.py | 24 ++++++++++++------------ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/heat/engine/clients/os/heat_plugin.py b/heat/engine/clients/os/heat_plugin.py index e93a418c2e..49240ddf2c 100644 --- a/heat/engine/clients/os/heat_plugin.py +++ b/heat/engine/clients/os/heat_plugin.py @@ -13,6 +13,7 @@ from oslo_config import cfg import six +from six.moves import urllib from heatclient import client as hc from heatclient import exc @@ -91,12 +92,23 @@ class HeatClientPlugin(client_plugin.ClientPlugin): def get_watch_server_url(self): cfn_url = self.get_heat_cfn_url() - url_parts = cfn_url.split(':') - port_and_version = url_parts[-1].split('/') - port_and_version[0] = ( - six.text_type(cfg.CONF.heat_api_cloudwatch.bind_port)) - url_parts[-1] = '/'.join(port_and_version) - return ':'.join(url_parts) + parsed_url = urllib.parse.urlparse(cfn_url) + separator = ':' + (host, separator, port) = parsed_url.netloc.partition(separator) + # The old url model, like http://localhost:port/v1 + if port: + watch_api_port = ( + six.text_type(cfg.CONF.heat_api_cloudwatch.bind_port)) + replaced_netloc = ':'.join([host, str(watch_api_port)]) + parsed_url = parsed_url._replace(netloc=replaced_netloc) + # The uwsgi url mode, like http://ip/heat-api-cfn/v1 + else: + paths = parsed_url.path.split('/') + paths[1] = 'heat-api-cloudwatch' + replaced_paths = '/'.join(paths) + parsed_url = parsed_url._replace(path=replaced_paths) + + return urllib.parse.urlunparse(parsed_url) def get_insecure_option(self): return self._get_client_option(CLIENT_NAME, 'insecure') diff --git a/heat/tests/clients/test_clients.py b/heat/tests/clients/test_clients.py index c15591d6d2..e99a01fe85 100644 --- a/heat/tests/clients/test_clients.py +++ b/heat/tests/clients/test_clients.py @@ -75,7 +75,7 @@ class ClientsTest(common.HeatTestCase): obj._get_client_option.return_value = result self.assertEqual(result, obj.get_heat_url()) - def _client_cfn_url(self): + def _client_cfn_url(self, use_uwsgi=False): con = mock.Mock() c = clients.Clients(con) con.clients = c @@ -83,7 +83,10 @@ class ClientsTest(common.HeatTestCase): obj._get_client_option = mock.Mock() obj._get_client_option.return_value = None obj.url_for = mock.Mock(name="url_for") - obj.url_for.return_value = "http://0.0.0.0:8000/v1/" + if use_uwsgi: + obj.url_for.return_value = "http://0.0.0.0/heat-api-cfn/v1/" + else: + obj.url_for.return_value = "http://0.0.0.0:8000/v1/" return obj def test_clients_get_heat_cfn_url(self): @@ -92,7 +95,13 @@ class ClientsTest(common.HeatTestCase): def test_clients_get_watch_server_url(self): obj = self._client_cfn_url() - self.assertEqual("http://0.0.0.0:8003/v1/", obj.get_watch_server_url()) + self.assertEqual("http://0.0.0.0:8003/v1/", + obj.get_watch_server_url()) + + def test_clients_get_watch_server_url_use_uwsgi(self): + obj = self._client_cfn_url(use_uwsgi=True) + self.assertEqual("http://0.0.0.0/heat-api-cloudwatch/v1/", + obj.get_watch_server_url()) def test_clients_get_heat_cfn_metadata_url(self): obj = self._client_cfn_url() diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index 2b94e0b303..dabf499587 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -786,14 +786,14 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_server_create_software_config(self, fake_url): - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip:port/v1' server = self._server_create_software_config() self.assertEqual({ 'os-collect-config': { 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip:port/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'software_config_s' @@ -805,13 +805,13 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_resolve_attribute_os_collect_config(self, fake_url): - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip/heat-api-cfn/v1' server = self._server_create_software_config() self.assertEqual({ 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip/heat-api-cfn/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'software_config_s' @@ -822,14 +822,14 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_server_create_software_config_metadata(self, fake_url): md = {'os-collect-config': {'polling_interval': 10}} - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip/heat-api-cfn/v1' server = self._server_create_software_config(md=md) self.assertEqual({ 'os-collect-config': { 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip/heat-api-cfn/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'software_config_s' @@ -1650,7 +1650,7 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_server_update_metadata_software_config(self, fake_url): - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip:port/v1' server, ud_tmpl = self._server_create_software_config( stack_name='update_meta_sc', ret_tmpl=True) @@ -1658,7 +1658,7 @@ class ServersTest(common.HeatTestCase): 'os-collect-config': { 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip:port/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'update_meta_sc' @@ -1678,7 +1678,7 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_server_update_metadata_software_config_merge(self, fake_url): md = {'os-collect-config': {'polling_interval': 10}} - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip/heat-api-cfn/v1' server, ud_tmpl = self._server_create_software_config( stack_name='update_meta_sc', ret_tmpl=True, md=md) @@ -1687,7 +1687,7 @@ class ServersTest(common.HeatTestCase): 'os-collect-config': { 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip/heat-api-cfn/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'update_meta_sc' @@ -1708,7 +1708,7 @@ class ServersTest(common.HeatTestCase): @mock.patch.object(heat_plugin.HeatClientPlugin, 'url_for') def test_server_update_software_config_transport(self, fake_url): md = {'os-collect-config': {'polling_interval': 10}} - fake_url.return_value = 'the-cfn-url' + fake_url.return_value = 'http://ip/heat-api-cfn/v1' server = self._server_create_software_config( stack_name='update_meta_sc', md=md) @@ -1716,7 +1716,7 @@ class ServersTest(common.HeatTestCase): 'os-collect-config': { 'cfn': { 'access_key_id': '4567', - 'metadata_url': 'the-cfn-url/v1/', + 'metadata_url': 'http://ip/heat-api-cfn/v1/', 'path': 'WebServer.Metadata', 'secret_access_key': '8901', 'stack_name': 'update_meta_sc'