From 15de6d43093d5e665e4def75358b1949454b229d Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Mon, 26 Aug 2013 14:37:05 +1000 Subject: [PATCH] Add support for local file urls Change-Id: Ie54508ade52b80790d11958a820998c902d10fd7 --- heat/common/urlfetch.py | 13 +++++++++++-- heat/tests/test_urlfetch.py | 25 ++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/heat/common/urlfetch.py b/heat/common/urlfetch.py index 623ce148..b2cdaf11 100644 --- a/heat/common/urlfetch.py +++ b/heat/common/urlfetch.py @@ -19,6 +19,7 @@ Utility for fetching a resource (e.g. a template) from a URL. import requests from requests import exceptions +import urllib2 import urlparse from heat.openstack.common import log as logging @@ -27,20 +28,28 @@ from heat.openstack.common.gettextutils import _ logger = logging.getLogger(__name__) -def get(url): +def get(url, allowed_schemes=('http', 'https')): ''' Get the data at the specifier URL. The URL must use the http: or https: schemes. + The file: scheme is also supported if you override + the allowed_schemes argument. Raise an IOError if getting the data fails. ''' logger.info(_('Fetching data from %s') % url) components = urlparse.urlparse(url) - if components.scheme not in ('http', 'https'): + if components.scheme not in allowed_schemes: raise IOError('Invalid URL scheme %s' % components.scheme) + if components.scheme == 'file': + try: + return urllib2.urlopen(url).read() + except urllib2.URLError as uex: + raise IOError('Failed to retrieve template: %s' % str(uex)) + try: resp = requests.get(url) resp.raise_for_status() diff --git a/heat/tests/test_urlfetch.py b/heat/tests/test_urlfetch.py index 776d8d8f..df358b24 100644 --- a/heat/tests/test_urlfetch.py +++ b/heat/tests/test_urlfetch.py @@ -15,6 +15,8 @@ import requests from requests import exceptions +import urllib2 +import cStringIO from heat.common import urlfetch from heat.tests.common import HeatTestCase @@ -37,11 +39,32 @@ class UrlFetchTest(HeatTestCase): super(UrlFetchTest, self).setUp() self.m.StubOutWithMock(requests, 'get') - def test_file_scheme(self): + def test_file_scheme_default_behaviour(self): self.m.ReplayAll() self.assertRaises(IOError, urlfetch.get, 'file:///etc/profile') self.m.VerifyAll() + def test_file_scheme_supported(self): + data = '{ "foo": "bar" }' + url = 'file:///etc/profile' + + self.m.StubOutWithMock(urllib2, 'urlopen') + urllib2.urlopen(url).AndReturn(cStringIO.StringIO(data)) + self.m.ReplayAll() + + self.assertEqual(data, urlfetch.get(url, allowed_schemes=['file'])) + self.m.VerifyAll() + + def test_file_scheme_failure(self): + url = 'file:///etc/profile' + + self.m.StubOutWithMock(urllib2, 'urlopen') + urllib2.urlopen(url).AndRaise(urllib2.URLError('oops')) + self.m.ReplayAll() + + self.assertRaises(IOError, urlfetch.get, url, allowed_schemes=['file']) + self.m.VerifyAll() + def test_http_scheme(self): url = 'http://example.com/template' data = '{ "foo": "bar" }' -- 2.45.2