Stop Connection class modifying os_options parameter

When a caller passes an os_options dict to the Connection class
constructor, the constructor may modify the os_options dict,
which can surprise the caller if they re-use the os_options
dict. Specifically the os_options tenant_name and object_storage_url
may be modified, and the changed values would then leak through to a
subsequent Connection constructed using the same os_options dict.

This fix simply constructs a new dict from the supplied os_options.
The patch also adds a test that covers this and also verifies that
a preauth_url passed as a keyword arg to Connection() will take
precedence over any object_storage_url in an os_options parameter.

Closes-Bug: 1488070
Change-Id: Ic6b5cf3ac68c505de155619f2610be9529e15432
This commit is contained in:
Alistair Coles 2015-08-24 12:34:45 +01:00
parent b4b9254bc3
commit 4b310083df
2 changed files with 28 additions and 1 deletions
swiftclient
tests/unit

@ -1290,7 +1290,7 @@ class Connection(object):
self.starting_backoff = starting_backoff
self.max_backoff = max_backoff
self.auth_version = auth_version
self.os_options = os_options or {}
self.os_options = dict(os_options or {})
if tenant_name:
self.os_options['tenant_name'] = tenant_name
if preauthurl:

@ -1481,6 +1481,33 @@ class TestConnection(MockHttpTest):
('HEAD', '/v1/AUTH_pre_url', '', {'x-auth-token': 'post_token'}),
])
def test_preauth_url_trumps_os_preauth_url(self):
storage_url = 'http://storage.example.com/v1/AUTH_pre_url'
os_storage_url = 'http://storage.example.com/v1/AUTH_os_pre_url'
os_preauth_options = {
'tenant_name': 'demo',
'object_storage_url': os_storage_url,
}
orig_os_preauth_options = dict(os_preauth_options)
conn = c.Connection('http://auth.example.com', 'user', 'password',
os_options=os_preauth_options, auth_version=2,
preauthurl=storage_url, tenant_name='not_demo')
fake_keystone = fake_get_auth_keystone(
storage_url='http://storage.example.com/v1/AUTH_post_url',
token='post_token')
fake_conn = self.fake_http_connection(200)
with mock.patch.multiple('swiftclient.client',
get_auth_keystone=fake_keystone,
http_connection=fake_conn,
sleep=mock.DEFAULT):
conn.head_account()
self.assertRequests([
('HEAD', '/v1/AUTH_pre_url', '', {'x-auth-token': 'post_token'}),
])
# check that Connection has not modified our os_options
self.assertEqual(orig_os_preauth_options, os_preauth_options)
def test_get_auth_sets_url_and_token(self):
with mock.patch('swiftclient.client.get_auth') as mock_get_auth:
mock_get_auth.return_value = (