From 6f55d2d9fc589f34548e5729a29492e4c7fd40da Mon Sep 17 00:00:00 2001 From: Gorka Eguileor Date: Tue, 5 May 2020 18:16:07 +0200 Subject: [PATCH] Google backup support client 1.8.2 Version 1.8.0 of the google-api-python-client package included the classic __version__ attribute that allowed us to know what version the client was running, but that's no longer the case on version 1.8.2. Which results in the following error when we use that library: AttributeError: module 'googleapiclient' has no attribute '__version__' Since we still need to know the version of the client we are running to determine the library to use for credentials we change how we get the version of the package. Now we use pkg_resources to get the version, which works even when there's no __version__ attribute. Change-Id: I24b1cf52c994a5fa0117fc2780d415981c596583 --- cinder/backup/drivers/gcs.py | 7 ++++--- .../unit/backup/drivers/test_backup_google.py | 20 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cinder/backup/drivers/gcs.py b/cinder/backup/drivers/gcs.py index 8326e7b7093..e372131c755 100644 --- a/cinder/backup/drivers/gcs.py +++ b/cinder/backup/drivers/gcs.py @@ -43,13 +43,13 @@ try: except ImportError: client = None -import googleapiclient from googleapiclient import discovery from googleapiclient import errors from googleapiclient import http from oslo_config import cfg from oslo_log import log as logging from oslo_utils import timeutils +import pkg_resources import six from cinder.backup import chunkeddriver @@ -174,8 +174,9 @@ class GoogleBackupDriver(chunkeddriver.ChunkedBackupDriver): # If we have google client that support google-auth library # (v1.6.0 or higher) and all required libraries are installed use # google-auth for the credentials - if (version.LooseVersion(googleapiclient.__version__) >= - version.LooseVersion('1.6.0') and service_account): + dist = pkg_resources.get_distribution('google-api-python-client') + if (version.LooseVersion(dist.version) >= version.LooseVersion('1.6.0') + and service_account): creds = service_account.Credentials.from_service_account_file( backup_credential) OAUTH_EXCEPTIONS = (gexceptions.RefreshError, diff --git a/cinder/tests/unit/backup/drivers/test_backup_google.py b/cinder/tests/unit/backup/drivers/test_backup_google.py index ec4de908c28..f0491206080 100644 --- a/cinder/tests/unit/backup/drivers/test_backup_google.py +++ b/cinder/tests/unit/backup/drivers/test_backup_google.py @@ -623,51 +623,59 @@ class GoogleBackupDriverTestCase(test.TestCase): self.assertEqual('none', result[0]) self.assertEqual(already_compressed_data, result[1]) - @mock.patch('googleapiclient.__version__', '1.5.5') + @mock.patch('pkg_resources.get_distribution') @mock.patch.object(google_dr.client.GoogleCredentials, 'from_stream') @mock.patch.object(google_dr.discovery, 'build') @mock.patch.object(google_dr, 'service_account') - def test_non_google_auth_version(self, account, build, from_stream): + def test_non_google_auth_version(self, account, build, from_stream, + get_dist_mock): # Prior to v1.6.0 Google api client doesn't support google-auth library + get_dist_mock.return_value.version = '1.5.5' google_dr.CONF.set_override('backup_gcs_credential_file', 'credentials_file') google_dr.GoogleBackupDriver(self.ctxt) + get_dist_mock.assert_called_once_with('google-api-python-client') from_stream.assert_called_once_with('credentials_file') account.Credentials.from_service_account_file.assert_not_called() build.assert_called_once_with('storage', 'v1', cache_discovery=False, credentials=from_stream.return_value) - @mock.patch('googleapiclient.__version__', '1.6.6') + @mock.patch('pkg_resources.get_distribution') @mock.patch.object(google_dr.client.GoogleCredentials, 'from_stream') @mock.patch.object(google_dr.discovery, 'build') @mock.patch.object(google_dr, 'service_account', None) - def test_no_httplib2_auth(self, build, from_stream): + def test_no_httplib2_auth(self, build, from_stream, get_dist_mock): # Google api client requires google-auth-httplib2 if not present we # use legacy credentials + get_dist_mock.return_value.version = '1.6.6' google_dr.CONF.set_override('backup_gcs_credential_file', 'credentials_file') google_dr.GoogleBackupDriver(self.ctxt) + get_dist_mock.assert_called_once_with('google-api-python-client') from_stream.assert_called_once_with('credentials_file') build.assert_called_once_with('storage', 'v1', cache_discovery=False, credentials=from_stream.return_value) - @mock.patch('googleapiclient.__version__', '1.6.6') + @mock.patch('pkg_resources.get_distribution') @mock.patch.object(google_dr, 'gexceptions', mock.Mock()) @mock.patch.object(google_dr.client.GoogleCredentials, 'from_stream') @mock.patch.object(google_dr.discovery, 'build') @mock.patch.object(google_dr, 'service_account') - def test_google_auth_used(self, account, build, from_stream): + def test_google_auth_used(self, account, build, from_stream, + get_dist_mock): # Google api client requires google-auth-httplib2 if not present we # use legacy credentials + get_dist_mock.return_value.version = '1.6.6' google_dr.CONF.set_override('backup_gcs_credential_file', 'credentials_file') google_dr.GoogleBackupDriver(self.ctxt) + get_dist_mock.assert_called_once_with('google-api-python-client') from_stream.assert_not_called() create_creds = account.Credentials.from_service_account_file create_creds.assert_called_once_with('credentials_file')