From 65680437e9073fe51173205639aed745b5f83a6a Mon Sep 17 00:00:00 2001 From: Adrian Vladu Date: Tue, 20 Jun 2017 14:04:30 +0300 Subject: [PATCH] Add POST support for _http_request when body is empty On call home, packet metadata service requires to perform a POST with an empty body. Adding support for POST on an empty body and support for all HTTP methods. Partially implements: blueprint packet-metadata-suport Change-Id: Ib1902c54ea3c4552313adddb3f944ea80a2a7fa0 --- cloudbaseinit/metadata/services/base.py | 19 ++++---- .../metadata/services/maasservice.py | 5 +- .../tests/metadata/services/test_base.py | 47 +++++++++++-------- .../metadata/services/test_maasservice.py | 2 +- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/cloudbaseinit/metadata/services/base.py b/cloudbaseinit/metadata/services/base.py index 1b4dda13..a26562be 100644 --- a/cloudbaseinit/metadata/services/base.py +++ b/cloudbaseinit/metadata/services/base.py @@ -248,18 +248,21 @@ class BaseHTTPMetadataService(BaseMetadataService): else: return self._https_allow_insecure - def _http_request(self, url, data=None, headers=None): + def _http_request(self, url, data=None, headers=None, method=None): """Get content for received url.""" if not url.startswith("http"): url = requests.compat.urljoin(self._base_url, url) - request_action = requests.get if not data else requests.post - if not data: - LOG.debug('Getting metadata from: %s', url) - else: - LOG.debug('Posting data to %s', url) + if not method: + if data: + method = "POST" + else: + method = "GET" + method = method.upper() - response = request_action(url=url, data=data, headers=headers, - verify=self._verify_https_request()) + LOG.debug('Executing http request %s at %s', method, url) + response = requests.request(method=method, url=url, data=data, + headers=headers, + verify=self._verify_https_request()) response.raise_for_status() return response.content diff --git a/cloudbaseinit/metadata/services/maasservice.py b/cloudbaseinit/metadata/services/maasservice.py index 81b7d16a..d477e7b3 100644 --- a/cloudbaseinit/metadata/services/maasservice.py +++ b/cloudbaseinit/metadata/services/maasservice.py @@ -97,14 +97,15 @@ class MaaSHttpService(base.BaseHTTPMetadataService): headers = client.sign(url, realm=realm)[1] return headers - def _http_request(self, url, data=None, headers=None): + def _http_request(self, url, data=None, headers=None, method=None): """Get content for received url.""" if not url.startswith("http"): url = requests.compat.urljoin(self._base_url, url) headers = {} if headers is None else headers headers.update(self._get_oauth_headers(url)) - return super(MaaSHttpService, self)._http_request(url, data, headers) + return super(MaaSHttpService, self)._http_request(url, data, headers, + method) def get_host_name(self): return self._get_cache_data('%s/meta-data/local-hostname' % diff --git a/cloudbaseinit/tests/metadata/services/test_base.py b/cloudbaseinit/tests/metadata/services/test_base.py index 93b97640..01f414a2 100644 --- a/cloudbaseinit/tests/metadata/services/test_base.py +++ b/cloudbaseinit/tests/metadata/services/test_base.py @@ -80,12 +80,12 @@ class TestBaseHTTPMetadataService(unittest.TestCase): def test_verify_https_request_with_ca_bundle(self): self._test_verify_https_request(https_ca_bundle="/path/to/resource") - @mock.patch('requests.post') - @mock.patch('requests.get') + @mock.patch('requests.request') @mock.patch("cloudbaseinit.metadata.services.base.BaseHTTPMetadataService." "_verify_https_request") - def _test_http_request(self, mock_verify, mock_get, mock_post, - mock_url, mock_data=None, mock_headers=None): + def _test_http_request(self, mock_verify, mock_request, mock_url, + mock_data=None, mock_headers=None, mock_method=None, + expected_method='GET'): if not mock_url.startswith('http'): mock_url = requests.compat.urljoin(self._mock_base_url, mock_url) @@ -93,24 +93,17 @@ class TestBaseHTTPMetadataService(unittest.TestCase): mock_response_status = mock.Mock() mock_response.raise_for_status = mock_response_status mock_response.content = mock.sentinel.content + mock_request.return_value = mock_response - mock_get.return_value = mock_response - mock_post.return_value = mock_response mock_verify.return_value = mock.sentinel.verify response = self._service._http_request(url=mock_url, data=mock_data, - headers=mock_headers) + headers=mock_headers, + method=mock_method) - if mock_data: - mock_post.assert_called_once_with( - url=mock_url, data=mock_data, headers=mock_headers, - verify=mock.sentinel.verify - ) - else: - mock_get.assert_called_once_with( - url=mock_url, data=mock_data, headers=mock_headers, - verify=mock.sentinel.verify - ) + mock_request.assert_called_once_with( + method=expected_method, url=mock_url, data=mock_data, + headers=mock_headers, verify=mock.sentinel.verify) mock_response_status.assert_called_once_with() self.assertEqual(response, mock.sentinel.content) @@ -118,12 +111,28 @@ class TestBaseHTTPMetadataService(unittest.TestCase): def test_http_get_request(self): self._test_http_request(mock_url="/path/to/resource", mock_data=None, - mock_headers={}) + mock_headers={}, expected_method="GET") def test_http_post_request(self): self._test_http_request(mock_url="/path/to/resource", mock_data={"X-Cloudbase-Init", True}, - mock_headers={}) + mock_headers={}, expected_method="POST") + + def test_http_force_post_request(self): + self._test_http_request(mock_url="/path/to/resource", + mock_data=None, mock_headers={}, + mock_method="post", expected_method="POST") + + def test_http_force_get_request(self): + self._test_http_request(mock_url="/path/to/resource", + mock_data={"X-Cloudbase-Init", True}, + mock_headers={}, mock_method="get", + expected_method="GET") + + def test_http_force_head_request(self): + self._test_http_request(mock_url="/path/to/resource", + mock_headers={}, mock_method="head", + expected_method="HEAD") @mock.patch('requests.compat.urljoin') @mock.patch("cloudbaseinit.metadata.services.base." diff --git a/cloudbaseinit/tests/metadata/services/test_maasservice.py b/cloudbaseinit/tests/metadata/services/test_maasservice.py index 3d21e075..1f5cd268 100644 --- a/cloudbaseinit/tests/metadata/services/test_maasservice.py +++ b/cloudbaseinit/tests/metadata/services/test_maasservice.py @@ -100,7 +100,7 @@ class MaaSHttpServiceTest(unittest.TestCase): def test_http_request(self, mock_ouath_headers, mock_http_request): mock_url = "fake.url" self._maasservice._http_request(mock_url) - mock_http_request.assert_called_once_with(mock_url, None, {}) + mock_http_request.assert_called_once_with(mock_url, None, {}, None) @mock.patch("cloudbaseinit.metadata.services.maasservice.MaaSHttpService" "._get_cache_data")