From: Zane Bitter Date: Thu, 6 Dec 2012 18:35:05 +0000 (+0100) Subject: Add a common implementation for fetching a URL X-Git-Tag: 2014.1~1125 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=d7568d08b23488e9651b4fe1fc57815348c4f45c;p=openstack-build%2Fheat-build.git Add a common implementation for fetching a URL There are multiple implementations of fetching a template from a URL, so add a common one where changes can be shared. Change-Id: I9c834efa71f97360dafb741e26713e3f3c124b6f Signed-off-by: Zane Bitter --- diff --git a/heat/common/urlfetch.py b/heat/common/urlfetch.py new file mode 100644 index 00000000..db17c327 --- /dev/null +++ b/heat/common/urlfetch.py @@ -0,0 +1,45 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# +# 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. + +''' +Utility for fetching a resource (e.g. a template) from a URL. +''' + +import urllib2 +import urlparse + +from heat.common import exception + +from heat.openstack.common import log as logging + +logger = logging.getLogger(__name__) + + +def get(url): + ''' + Get the data at the specifier URL. + + The URL must use the http: or https: schemes. + 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'): + raise urllib2.URLError('Invalid URL scheme %s' % components.scheme) + + response = urllib2.urlopen(url) + return response.read() diff --git a/heat/tests/test_urlfetch.py b/heat/tests/test_urlfetch.py new file mode 100644 index 00000000..a2d39529 --- /dev/null +++ b/heat/tests/test_urlfetch.py @@ -0,0 +1,73 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# +# 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 mox +import nose +from nose.plugins.attrib import attr +import StringIO +import unittest +import urllib2 + +from heat.common import urlfetch + + +@attr(tag=['unit', 'urlfetch']) +@attr(speed='fast') +class UrlFetchTest(unittest.TestCase): + def setUp(self): + self.m = mox.Mox() + self.m.StubOutWithMock(urllib2, 'urlopen') + + def tearDown(self): + self.m.UnsetStubs() + + def test_file_scheme(self): + self.m.ReplayAll() + self.assertRaises(IOError, urlfetch.get, 'file:///etc/profile') + self.m.VerifyAll() + + def test_http_scheme(self): + url = 'http://example.com/template' + data = '{ "foo": "bar" }' + + urllib2.urlopen(url).AndReturn(StringIO.StringIO(data)) + self.m.ReplayAll() + + self.assertEqual(urlfetch.get(url), data) + self.m.VerifyAll() + + def test_https_scheme(self): + url = 'https://example.com/template' + data = '{ "foo": "bar" }' + + urllib2.urlopen(url).AndReturn(StringIO.StringIO(data)) + self.m.ReplayAll() + + self.assertEqual(urlfetch.get(url), data) + self.m.VerifyAll() + + def test_http_error(self): + url = 'http://example.com/template' + + urllib2.urlopen(url).AndRaise(urllib2.URLError('fubar')) + self.m.ReplayAll() + + self.assertRaises(IOError, urlfetch.get, url) + self.m.VerifyAll() + + def test_garbage(self): + self.m.ReplayAll() + self.assertRaises(IOError, urlfetch.get, 'wibble') + self.m.VerifyAll()