summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-08-15 21:48:06 +0000
committerGerrit Code Review <review@openstack.org>2018-08-15 21:48:06 +0000
commitb506e3cf793b2fccd4f17f78159d76890786fc59 (patch)
tree3ba0c6bc23f83308ee52372d5c78693c62cfe7bb
parent0c41ab9ae21816bccc6da0fe561e1b1bfe8d1370 (diff)
parentf601cfccf1d8e2e314a270943d91e8aa1932f2a4 (diff)
Merge "Support RFC1738 quoted chars in passwords"
-rw-r--r--glance/db/sqlalchemy/alembic_migrations/__init__.py10
-rw-r--r--glance/tests/unit/test_manage.py13
2 files changed, 22 insertions, 1 deletions
diff --git a/glance/db/sqlalchemy/alembic_migrations/__init__.py b/glance/db/sqlalchemy/alembic_migrations/__init__.py
index f35e47d..ef9faf3 100644
--- a/glance/db/sqlalchemy/alembic_migrations/__init__.py
+++ b/glance/db/sqlalchemy/alembic_migrations/__init__.py
@@ -35,7 +35,15 @@ def get_alembic_config(engine=None):
35 config = alembic_config.Config(os.path.abspath(ini_path)) 35 config = alembic_config.Config(os.path.abspath(ini_path))
36 if engine is None: 36 if engine is None:
37 engine = db_api.get_engine() 37 engine = db_api.get_engine()
38 config.set_main_option('sqlalchemy.url', str(engine.url)) 38 # str(sqlalchemy.engine.url.URL) returns a RFC-1738 quoted URL.
39 # This means that a password like "foo@" will be turned into
40 # "foo%40". This causes a problem for set_main_option() here
41 # because that uses ConfigParser.set, which (by design) uses
42 # *python* interpolation to write the string out ... where "%" is
43 # the special python interpolation character! Avoid this
44 # mis-match by quoting all %'s for the set below.
45 quoted_engine_url = str(engine.url).replace('%', '%%')
46 config.set_main_option('sqlalchemy.url', quoted_engine_url)
39 return config 47 return config
40 48
41 49
diff --git a/glance/tests/unit/test_manage.py b/glance/tests/unit/test_manage.py
index b92c9a4..4da916b 100644
--- a/glance/tests/unit/test_manage.py
+++ b/glance/tests/unit/test_manage.py
@@ -21,9 +21,11 @@ from six.moves import StringIO
21 21
22from glance.cmd import manage 22from glance.cmd import manage
23from glance.common import exception 23from glance.common import exception
24from glance.db.sqlalchemy import alembic_migrations
24from glance.db.sqlalchemy import api as db_api 25from glance.db.sqlalchemy import api as db_api
25from glance.db.sqlalchemy import metadata as db_metadata 26from glance.db.sqlalchemy import metadata as db_metadata
26from glance.tests import utils as test_utils 27from glance.tests import utils as test_utils
28from sqlalchemy.engine.url import make_url as sqlalchemy_make_url
27 29
28 30
29class TestManageBase(test_utils.BaseTestCase): 31class TestManageBase(test_utils.BaseTestCase):
@@ -166,6 +168,17 @@ class TestManage(TestManageBase):
166 self.output = StringIO() 168 self.output = StringIO()
167 self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.output)) 169 self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.output))
168 170
171 def test_db_complex_password(self):
172 engine = mock.Mock()
173 # See comments in get_alembic_config; make an engine url with
174 # password characters that will be escaped, to ensure the
175 # resulting value makes it into alembic unaltered.
176 engine.url = sqlalchemy_make_url(
177 'mysql+pymysql://username:pw@%/!#$()@host:1234/dbname')
178 alembic_config = alembic_migrations.get_alembic_config(engine)
179 self.assertEqual(str(engine.url),
180 alembic_config.get_main_option('sqlalchemy.url'))
181
169 @mock.patch('glance.db.sqlalchemy.api.get_engine') 182 @mock.patch('glance.db.sqlalchemy.api.get_engine')
170 @mock.patch( 183 @mock.patch(
171 'glance.db.sqlalchemy.alembic_migrations.data_migrations.' 184 'glance.db.sqlalchemy.alembic_migrations.data_migrations.'