Use the new oslo py3kcompat.urlutils

Change-Id: I9e5d00a04460ef54d402b69f781d2a69a3bd0082
This commit is contained in:
Angus Salkeld 2013-12-04 13:46:51 +11:00
parent 70e321e60a
commit 782755e8a8
11 changed files with 55 additions and 53 deletions

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import urllib from heat.openstack.common.py3kcompat import urlutils
def get_collection_links(request, items): def get_collection_links(request, items):
@ -39,4 +39,4 @@ def _get_next_link(request, marker):
params = request.params.copy() params = request.params.copy()
params['marker'] = marker params['marker'] = marker
return "%s?%s" % (request.path_url, urllib.urlencode(params)) return "%s?%s" % (request.path_url, urlutils.urlencode(params))

View File

@ -18,10 +18,10 @@
"""Heat exception subclasses""" """Heat exception subclasses"""
import functools import functools
import urlparse
import sys import sys
from heat.openstack.common import log as logging from heat.openstack.common import log as logging
from heat.openstack.common.py3kcompat import urlutils
_FATAL_EXCEPTION_FORMAT_ERRORS = False _FATAL_EXCEPTION_FORMAT_ERRORS = False
@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
class RedirectException(Exception): class RedirectException(Exception):
def __init__(self, url): def __init__(self, url):
self.url = urlparse.urlparse(url) self.url = urlutils.urlparse(url)
class KeystoneError(Exception): class KeystoneError(Exception):

View File

@ -13,11 +13,10 @@
# under the License. # under the License.
import re import re
import urllib
import urlparse
import collections import collections
from heat.openstack.common import strutils from heat.openstack.common import strutils
from heat.openstack.common.py3kcompat import urlutils
class HeatIdentifier(collections.Mapping): class HeatIdentifier(collections.Mapping):
@ -63,10 +62,10 @@ class HeatIdentifier(collections.Mapping):
if fields[1] != 'openstack' or fields[2] != 'heat' or not path: if fields[1] != 'openstack' or fields[2] != 'heat' or not path:
raise ValueError(_('"%s" is not a valid Heat ARN') % arn) raise ValueError(_('"%s" is not a valid Heat ARN') % arn)
return cls(urllib.unquote(fields[4]), return cls(urlutils.unquote(fields[4]),
urllib.unquote(path.group(1)), urlutils.unquote(path.group(1)),
urllib.unquote(path.group(2)), urlutils.unquote(path.group(2)),
urllib.unquote(path.group(3))) urlutils.unquote(path.group(3)))
@classmethod @classmethod
def from_arn_url(cls, url): def from_arn_url(cls, url):
@ -75,7 +74,7 @@ class HeatIdentifier(collections.Mapping):
The URL is expected to contain a valid arn as part of the path The URL is expected to contain a valid arn as part of the path
''' '''
# Sanity check the URL # Sanity check the URL
urlp = urlparse.urlparse(url) urlp = urlutils.urlparse(url)
if (urlp.scheme not in ('http', 'https') or if (urlp.scheme not in ('http', 'https') or
not urlp.netloc or not urlp.path): not urlp.netloc or not urlp.path):
raise ValueError(_('"%s" is not a valid URL') % url) raise ValueError(_('"%s" is not a valid URL') % url)
@ -87,7 +86,7 @@ class HeatIdentifier(collections.Mapping):
raise ValueError(_('"%s" is not a valid ARN URL') % url) raise ValueError(_('"%s" is not a valid ARN URL') % url)
# the +1 is to skip the leading / # the +1 is to skip the leading /
url_arn = urlp.path[match.start() + 1:] url_arn = urlp.path[match.start() + 1:]
arn = urllib.unquote(url_arn) arn = urlutils.unquote(url_arn)
return cls.from_arn(arn) return cls.from_arn(arn)
def arn(self): def arn(self):
@ -95,21 +94,21 @@ class HeatIdentifier(collections.Mapping):
Return an ARN of the form: Return an ARN of the form:
arn:openstack:heat::<tenant>:stacks/<stack_name>/<stack_id><path> arn:openstack:heat::<tenant>:stacks/<stack_name>/<stack_id><path>
''' '''
return 'arn:openstack:heat::%s:%s' % (urllib.quote(self.tenant, ''), return 'arn:openstack:heat::%s:%s' % (urlutils.quote(self.tenant, ''),
self._tenant_path()) self._tenant_path())
def arn_url_path(self): def arn_url_path(self):
''' '''
Return an ARN quoted correctly for use in a URL Return an ARN quoted correctly for use in a URL
''' '''
return '/' + urllib.quote(self.arn(), '') return '/' + urlutils.quote(self.arn(), '')
def url_path(self): def url_path(self):
''' '''
Return a URL-encoded path segment of a URL in the form: Return a URL-encoded path segment of a URL in the form:
<tenant>/stacks/<stack_name>/<stack_id><path> <tenant>/stacks/<stack_name>/<stack_id><path>
''' '''
return '/'.join((urllib.quote(self.tenant, ''), self._tenant_path())) return '/'.join((urlutils.quote(self.tenant, ''), self._tenant_path()))
def _tenant_path(self): def _tenant_path(self):
''' '''
@ -117,9 +116,9 @@ class HeatIdentifier(collections.Mapping):
in the form: in the form:
stacks/<stack_name>/<stack_id><path> stacks/<stack_name>/<stack_id><path>
''' '''
return 'stacks/%s/%s%s' % (urllib.quote(self.stack_name, ''), return 'stacks/%s/%s%s' % (urlutils.quote(self.stack_name, ''),
urllib.quote(self.stack_id, ''), urlutils.quote(self.stack_id, ''),
urllib.quote(strutils.safe_encode( urlutils.quote(strutils.safe_encode(
self.path))) self.path)))
def _path_components(self): def _path_components(self):

View File

@ -19,8 +19,6 @@ Utility for fetching a resource (e.g. a template) from a URL.
import requests import requests
from requests import exceptions from requests import exceptions
import urllib2
import urlparse
from oslo.config import cfg from oslo.config import cfg
@ -28,6 +26,7 @@ cfg.CONF.import_opt('max_template_size', 'heat.common.config')
from heat.openstack.common import log as logging from heat.openstack.common import log as logging
from heat.openstack.common.gettextutils import _ from heat.openstack.common.gettextutils import _
from heat.openstack.common.py3kcompat import urlutils
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -43,15 +42,15 @@ def get(url, allowed_schemes=('http', 'https')):
''' '''
logger.info(_('Fetching data from %s') % url) logger.info(_('Fetching data from %s') % url)
components = urlparse.urlparse(url) components = urlutils.urlparse(url)
if components.scheme not in allowed_schemes: if components.scheme not in allowed_schemes:
raise IOError(_('Invalid URL scheme %s') % components.scheme) raise IOError(_('Invalid URL scheme %s') % components.scheme)
if components.scheme == 'file': if components.scheme == 'file':
try: try:
return urllib2.urlopen(url).read() return urlutils.urlopen(url).read()
except urllib2.URLError as uex: except urlutils.URLError as uex:
raise IOError(_('Failed to retrieve template: %s') % str(uex)) raise IOError(_('Failed to retrieve template: %s') % str(uex))
try: try:

View File

@ -21,8 +21,6 @@ import json
import os import os
import pkgutil import pkgutil
from urlparse import urlparse
from oslo.config import cfg from oslo.config import cfg
from heat.common import exception from heat.common import exception
@ -31,6 +29,8 @@ from heat.engine import scheduler
from heat.openstack.common import log as logging from heat.openstack.common import log as logging
from heat.openstack.common.gettextutils import _ from heat.openstack.common.gettextutils import _
from heat.openstack.common import uuidutils from heat.openstack.common import uuidutils
from heat.openstack.common.py3kcompat import urlutils
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -175,8 +175,8 @@ def build_userdata(resource, userdata=None, instance_user=None):
# Create a boto config which the cfntools on the host use to know # Create a boto config which the cfntools on the host use to know
# where the cfn and cw API's are to be accessed # where the cfn and cw API's are to be accessed
cfn_url = urlparse(cfg.CONF.heat_metadata_server_url) cfn_url = urlutils.urlparse(cfg.CONF.heat_metadata_server_url)
cw_url = urlparse(cfg.CONF.heat_watch_server_url) cw_url = urlutils.urlparse(cfg.CONF.heat_watch_server_url)
is_secure = cfg.CONF.instance_connection_is_secure is_secure = cfg.CONF.instance_connection_is_secure
vcerts = cfg.CONF.instance_connection_https_validate_certificates vcerts = cfg.CONF.instance_connection_https_validate_certificates
boto_cfg = "\n".join(["[Boto]", boto_cfg = "\n".join(["[Boto]",

View File

@ -13,11 +13,12 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from urlparse import urlparse
from heat.engine import clients from heat.engine import clients
from heat.engine import resource from heat.engine import resource
from heat.openstack.common import log as logging from heat.openstack.common import log as logging
from heat.openstack.common.py3kcompat import urlutils
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -126,7 +127,7 @@ class S3Bucket(resource.Resource):
def _resolve_attribute(self, name): def _resolve_attribute(self, name):
url = self.swift().get_auth()[0] url = self.swift().get_auth()[0]
parsed = list(urlparse(url)) parsed = list(urlutils.urlparse(url))
if name == 'DomainName': if name == 'DomainName':
return parsed[1].split(':')[0] return parsed[1].split(':')[0]
elif name == 'WebsiteURL': elif name == 'WebsiteURL':

View File

@ -13,13 +13,14 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from urlparse import urlparse
from heat.common import exception from heat.common import exception
from heat.engine import resource from heat.engine import resource
from heat.openstack.common import log as logging
from heat.engine import clients from heat.engine import clients
from heat.openstack.common import log as logging
from heat.openstack.common.py3kcompat import urlutils
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -112,7 +113,7 @@ class SwiftContainer(resource.Resource):
def FnGetAtt(self, key): def FnGetAtt(self, key):
url, token_id = self.swift().get_auth() url, token_id = self.swift().get_auth()
parsed = list(urlparse(url)) parsed = list(urlutils.urlparse(url))
if key == 'DomainName': if key == 'DomainName':
return parsed[1].split(':')[0] return parsed[1].split(':')[0]
elif key == 'WebsiteURL': elif key == 'WebsiteURL':

View File

@ -13,9 +13,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import urllib
import urlparse
from oslo.config import cfg from oslo.config import cfg
from keystoneclient.contrib.ec2 import utils as ec2_utils from keystoneclient.contrib.ec2 import utils as ec2_utils
@ -27,6 +24,8 @@ from heat.engine import resource
from heat.openstack.common import log from heat.openstack.common import log
from heat.openstack.common.gettextutils import _ from heat.openstack.common.gettextutils import _
from heat.openstack.common.py3kcompat import urlutils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
SIGNAL_TYPES = ( SIGNAL_TYPES = (
@ -85,7 +84,7 @@ class SignalResponder(resource.Resource):
waitcond_url = cfg.CONF.heat_waitcondition_server_url waitcond_url = cfg.CONF.heat_waitcondition_server_url
signal_url = waitcond_url.replace('/waitcondition', signal_type) signal_url = waitcond_url.replace('/waitcondition', signal_type)
host_url = urlparse.urlparse(signal_url) host_url = urlutils.urlparse(signal_url)
path = self.identifier().arn_url_path() path = self.identifier().arn_url_path()
credentials = self.keystone().get_ec2_keypair(self.resource_id) credentials = self.keystone().get_ec2_keypair(self.resource_id)
@ -94,7 +93,7 @@ class SignalResponder(resource.Resource):
# prcessing in the CFN API (ec2token.py) has an unquoted path, so we # prcessing in the CFN API (ec2token.py) has an unquoted path, so we
# need to calculate the signature with the path component unquoted, but # need to calculate the signature with the path component unquoted, but
# ensure the actual URL contains the quoted version... # ensure the actual URL contains the quoted version...
unquoted_path = urllib.unquote(host_url.path + path) unquoted_path = urlutils.unquote(host_url.path + path)
request = {'host': host_url.netloc.lower(), request = {'host': host_url.netloc.lower(),
'verb': SIGNAL_VERB[signal_type], 'verb': SIGNAL_VERB[signal_type],
'path': unquoted_path, 'path': unquoted_path,
@ -108,7 +107,7 @@ class SignalResponder(resource.Resource):
signer = ec2_utils.Ec2Signer(credentials.secret) signer = ec2_utils.Ec2Signer(credentials.secret)
request['params']['Signature'] = signer.generate(request) request['params']['Signature'] = signer.generate(request)
qs = urllib.urlencode(request['params']) qs = urlutils.urlencode(request['params'])
url = "%s%s?%s" % (signal_url.lower(), url = "%s%s?%s" % (signal_url.lower(),
path, qs) path, qs)

View File

@ -13,10 +13,10 @@
# under the License. # under the License.
import mock import mock
import urlparse
from heat.tests.common import HeatTestCase from heat.tests.common import HeatTestCase
from heat.api.openstack.v1.views import views_common from heat.api.openstack.v1.views import views_common
from heat.openstack.common.py3kcompat import urlutils
class TestViewsCommon(HeatTestCase): class TestViewsCommon(HeatTestCase):
@ -74,10 +74,11 @@ class TestViewsCommon(HeatTestCase):
next_link = filter(lambda link: link['rel'] == 'next', links).pop() next_link = filter(lambda link: link['rel'] == 'next', links).pop()
url = next_link['href'] url = next_link['href']
query_string = urlparse.urlparse(url).query query_string = urlutils.urlparse(url).query
params = urlparse.parse_qs(query_string) params = {}
self.assertEqual('2', params['limit'][0]) params.update(urlutils.parse_qsl(query_string))
self.assertEqual('bar', params['foo'][0]) self.assertEqual('2', params['limit'])
self.assertEqual('bar', params['foo'])
def test_get_collection_links_handles_invalid_limits(self): def test_get_collection_links_handles_invalid_limits(self):
self.setUpGetCollectionLinks() self.setUpGetCollectionLinks()

View File

@ -15,7 +15,6 @@
import requests import requests
from requests import exceptions from requests import exceptions
import urllib2
import cStringIO import cStringIO
from oslo.config import cfg from oslo.config import cfg
@ -23,6 +22,8 @@ from oslo.config import cfg
from heat.common import urlfetch from heat.common import urlfetch
from heat.tests.common import HeatTestCase from heat.tests.common import HeatTestCase
from heat.openstack.common.py3kcompat import urlutils
class Response: class Response:
def __init__(self, buf=''): def __init__(self, buf=''):
@ -51,8 +52,8 @@ class UrlFetchTest(HeatTestCase):
data = '{ "foo": "bar" }' data = '{ "foo": "bar" }'
url = 'file:///etc/profile' url = 'file:///etc/profile'
self.m.StubOutWithMock(urllib2, 'urlopen') self.m.StubOutWithMock(urlutils, 'urlopen')
urllib2.urlopen(url).AndReturn(cStringIO.StringIO(data)) urlutils.urlopen(url).AndReturn(cStringIO.StringIO(data))
self.m.ReplayAll() self.m.ReplayAll()
self.assertEqual(data, urlfetch.get(url, allowed_schemes=['file'])) self.assertEqual(data, urlfetch.get(url, allowed_schemes=['file']))
@ -61,8 +62,8 @@ class UrlFetchTest(HeatTestCase):
def test_file_scheme_failure(self): def test_file_scheme_failure(self):
url = 'file:///etc/profile' url = 'file:///etc/profile'
self.m.StubOutWithMock(urllib2, 'urlopen') self.m.StubOutWithMock(urlutils, 'urlopen')
urllib2.urlopen(url).AndRaise(urllib2.URLError('oops')) urlutils.urlopen(url).AndRaise(urlutils.URLError('oops'))
self.m.ReplayAll() self.m.ReplayAll()
self.assertRaises(IOError, urlfetch.get, url, allowed_schemes=['file']) self.assertRaises(IOError, urlfetch.get, url, allowed_schemes=['file'])

View File

@ -14,12 +14,13 @@
# limitations under the License. # limitations under the License.
import httplib2 import httplib2
import urlparse
from novaclient import client as base_client from novaclient import client as base_client
from novaclient.v1_1 import client from novaclient.v1_1 import client
from heat.tests import fakes from heat.tests import fakes
from heat.openstack.common.py3kcompat import urlutils
class FakeClient(fakes.FakeClient, client.Client): class FakeClient(fakes.FakeClient, client.Client):
@ -45,7 +46,7 @@ class FakeHTTPClient(base_client.HTTPClient):
assert 'body' in kwargs assert 'body' in kwargs
# Call the method # Call the method
args = urlparse.parse_qsl(urlparse.urlparse(url)[4]) args = urlutils.parse_qsl(urlutils.urlparse(url)[4])
kwargs.update(args) kwargs.update(args)
munged_url = url.rsplit('?', 1)[0] munged_url = url.rsplit('?', 1)[0]
munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_') munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_')