Remove more unused pieces of infra_libs:
* app
* command_line
* unused methods in httplib2_utils
* utils.rmtree
This should be the last bit of cleanup here for now, then we will
switch the remaining tests to execute with python3.
Change-Id: I0b5d7637e5b28d2df2a64bd76d50972321f451fa
Reviewed-on: https://chromium-review.googlesource.com/c/infra/infra/+/5224894
Commit-Queue: Vadim Shtayura <vadimsh@chromium.org>
Auto-Submit: Brian Ryner <bryner@google.com>
Reviewed-by: Vadim Shtayura <vadimsh@chromium.org>
Cr-Commit-Position: refs/heads/main@{#62551}
NOKEYCHECK=True
GitOrigin-RevId: 400edfacf2b42389f034eeba1b0ef3798c9b8d2c
diff --git a/infra_libs/__init__.py b/infra_libs/__init__.py
index 3f99163..732c11a 100644
--- a/infra_libs/__init__.py
+++ b/infra_libs/__init__.py
@@ -5,18 +5,8 @@
from . import ts_mon # Must be imported first so httplib2_utils can import it.
from infra_libs.httplib2_utils import AuthError
-from infra_libs.httplib2_utils import get_authenticated_http
-from infra_libs.httplib2_utils import get_signed_jwt_assertion_credentials
from infra_libs.httplib2_utils import RetriableHttp, InstrumentedHttp, HttpMock
from infra_libs.httplib2_utils import SERVICE_ACCOUNTS_CREDS_ROOT
from infra_libs.utils import read_json_as_utf8
from infra_libs.utils import parse_rfc3339_epoch
-from infra_libs.utils import rmtree
from infra_libs.utils import temporary_directory
-
-import sys
-
-if sys.platform == 'linux2': # pragma: no cover
- from . import _command_line_linux as command_line
-else: # pragma: no cover
- from . import _command_line_stub as command_line
diff --git a/infra_libs/_command_line_linux.py b/infra_libs/_command_line_linux.py
deleted file mode 100644
index d453fbe..0000000
--- a/infra_libs/_command_line_linux.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import ctypes
-import ctypes.util
-import sys
-
-
-_CACHED_CMDLINE_LENGTH = None
-
-
-def set_command_line(cmdline):
- """Replaces the commandline of this process as seen by ps."""
-
- # Get the current commandline.
- argc = ctypes.c_int()
- argv = ctypes.POINTER(ctypes.c_char_p)()
- ctypes.pythonapi.Py_GetArgcArgv(ctypes.byref(argc), ctypes.byref(argv))
-
- global _CACHED_CMDLINE_LENGTH
- if _CACHED_CMDLINE_LENGTH is None:
- # Each argument is terminated by a null-byte, so the length of the whole
- # thing in memory is the sum of all the argument byte-lengths, plus 1 null
- # byte for each.
- _CACHED_CMDLINE_LENGTH = sum(
- len(argv[i]) for i in range(0, argc.value)) + argc.value
-
- # Pad the cmdline string to the required length. If it's longer than the
- # current commandline, truncate it.
- if len(cmdline) >= _CACHED_CMDLINE_LENGTH:
- new_cmdline = ctypes.c_char_p(cmdline[:_CACHED_CMDLINE_LENGTH-1] + '\0')
- else:
- new_cmdline = ctypes.c_char_p(cmdline.ljust(_CACHED_CMDLINE_LENGTH, '\0'))
-
- # Replace the old commandline.
- libc = ctypes.CDLL(ctypes.util.find_library('c'))
- libc.memcpy(argv.contents, new_cmdline, _CACHED_CMDLINE_LENGTH)
diff --git a/infra_libs/_command_line_stub.py b/infra_libs/_command_line_stub.py
deleted file mode 100644
index bec0969..0000000
--- a/infra_libs/_command_line_stub.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-def set_command_line(_cmdline):
- raise NotImplementedError()
diff --git a/infra_libs/app.py b/infra_libs/app.py
deleted file mode 100644
index 1aafe7c..0000000
--- a/infra_libs/app.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import argparse
-import datetime
-import logging
-import os
-import sys
-
-import psutil
-
-from infra_libs import logs
-from infra_libs import ts_mon
-
-
-class BaseApplication(object):
- """Encapsulates common boilerplate for setting up an application.
-
- Subclasses must implement the main() method, and will usually also implement
- add_argparse_options().
-
- By default this will initialise logging and timeseries monitoring (ts_mon)
- modules.
-
- Minimal example::
-
- from infra_libs import app
-
- class MyApplication(app.BaseApplication):
- def main(self, opts):
- # Do stuff.
-
- if __name__ == '__main__':
- MyApplication().run()
-
- Class variables (override these in your class definition):
- PROG_NAME: The program name to display in the --help message. Defaults to
- sys.argv[0]. Passed to argparse.ArgumentParser.
- DESCRIPTION: Text to display in the --help message. Passed to
- argparse.ArgumentParser.
- USES_STANDARD_LOGGING: Whether to configure the standard logging libraries.
- Defaults to True.
- USES_TS_MON: Whether to configure timeseries monitoring. Defaults to True.
-
- Instance variables (use these in your application):
- opts: The argparse.Namespace containing parsed commandline arguments.
- """
-
- PROG_NAME = None
- DESCRIPTION = None
- USES_STANDARD_LOGGING = True
- USES_TS_MON = True
-
- def __init__(self):
- self.opts = None
- self.parser = None
-
- def add_argparse_options(self, parser):
- """Register any arguments used by this application.
-
- Override this method and call parser.add_argument().
-
- Args:
- parser: An argparse.ArgumentParser object.
- """
-
- if self.USES_STANDARD_LOGGING:
- logs.add_argparse_options(parser)
- if self.USES_TS_MON:
- ts_mon.add_argparse_options(parser)
-
- def process_argparse_options(self, options):
- """Process any commandline arguments.
-
- Args:
- options: An argparse.Namespace object.
- """
-
- if self.USES_STANDARD_LOGGING:
- logs.process_argparse_options(options)
- if self.USES_TS_MON:
- ts_mon.process_argparse_options(options)
-
- def main(self, opts):
- """Your application's main method.
-
- Do the work of your application here. When this method returns the
- application will exit.
-
- Args:
- opts: An argparse.Namespace containing parsed commandline options. This
- is passed as an argument for convenience but is also accessible as an
- instance variable (self.opts).
-
- Return:
- An integer exit status, or None to use an exit status of 0.
- """
- raise NotImplementedError
-
- def run(self, args=None):
- """Main application entry point."""
-
- if args is None: # pragma: no cover
- args = sys.argv
-
- # Add and parse commandline args.
- self.parser = argparse.ArgumentParser(
- description=self.DESCRIPTION,
- prog=self.PROG_NAME or args[0],
- formatter_class=argparse.RawTextHelpFormatter)
-
- self.add_argparse_options(self.parser)
- self.opts = self.parser.parse_args(args[1:])
- self.process_argparse_options(self.opts)
-
- # Print a startup log message.
- logging.info('Process started at %s', datetime.datetime.utcfromtimestamp(
- psutil.Process().create_time()).isoformat())
- logging.info('Command line arguments:')
- for index, arg in enumerate(sys.argv):
- logging.info('argv[%d]: %s', index, arg)
- logging.info('Process id %d', os.getpid())
- logging.info('Current working directory %s', os.getcwd())
-
- # Run the application's main function.
- try:
- status = self.main(self.opts)
- except Exception:
- logging.exception('Uncaught exception, exiting:')
- if self.USES_TS_MON:
- # Flushing ts_mon to try to report the exception.
- ts_mon.flush()
- status = 1
-
- sys.exit(status)
diff --git a/infra_libs/httplib2_utils.py b/infra_libs/httplib2_utils.py
index 934c054..f72552f 100644
--- a/infra_libs/httplib2_utils.py
+++ b/infra_libs/httplib2_utils.py
@@ -22,8 +22,6 @@
from infra_libs.ts_mon.common import http_metrics
from infra_libs.utils import parse_rfc3339_epoch
-DEFAULT_SCOPES = ['email']
-
# default timeout for http requests, in seconds
DEFAULT_TIMEOUT = 30
@@ -38,135 +36,6 @@
pass
-def load_service_account_credentials(credentials_filename,
- service_accounts_creds_root=None):
- """Loads and validate a credential JSON file.
-
- Example of a well-formatted file:
- {
- "private_key_id": "4168d274cdc7a1eaef1c59f5b34bdf255",
- "private_key": ("-----BEGIN PRIVATE KEY-----\nMIIhkiG9w0BAQEFAASCAmEwsd"
- "sdfsfFd\ngfxFChctlOdTNm2Wrr919Nx9q+sPV5ibyaQt5Dgn89fKV"
- "jftrO3AMDS3sMjaE4Ib\nZwJgy90wwBbMT7/YOzCgf5PZfivUe8KkB"
- -----END PRIVATE KEY-----\n",
- "client_email": "234243-rjstu8hi95iglc8at3@developer.gserviceaccount.com",
- "client_id": "234243-rjstu8hi95iglc8at3.apps.googleusercontent.com",
- "type": "service_account"
- }
-
- Args:
- credentials_filename (str): path to a .json file containing credentials
- for a Cloud platform service account.
-
- Keyword Args:
- service_accounts_creds_root (str or None): location where all service
- account credentials are stored. ``credentials_filename`` is relative
- to this path. None means 'use default location'.
-
- Raises:
- AuthError: if the file content is invalid.
- """
- service_accounts_creds_root = (service_accounts_creds_root
- or SERVICE_ACCOUNTS_CREDS_ROOT)
-
- service_account_file = os.path.join(service_accounts_creds_root,
- credentials_filename)
- try:
- with open(service_account_file, 'r') as f:
- key = json.load(f)
- except ValueError as e:
- raise AuthError('Parsing of file as JSON failed (%s): %s',
- e, service_account_file)
-
- if key.get('type') != 'service_account':
- msg = ('Credentials type must be for a service_account, got %s.'
- ' Check content of %s' % (key.get('type'), service_account_file))
- logging.error(msg)
- raise AuthError(msg)
-
- if not key.get('client_email'):
- msg = ('client_email field missing in credentials json file. '
- ' Check content of %s' % service_account_file)
- logging.error(msg)
- raise AuthError(msg)
-
- if not key.get('private_key'):
- msg = ('private_key field missing in credentials json. '
- ' Check content of %s' % service_account_file)
- logging.error(msg)
- raise AuthError(msg)
-
- return key
-
-
-def get_signed_jwt_assertion_credentials(credentials_filename,
- scope=None,
- service_accounts_creds_root=None):
- """Factory for SignedJwtAssertionCredentials
-
- Reads and validate the json credential file.
-
- Args:
- credentials_filename (str): path to the service account key file.
- See load_service_account_credentials() docstring for the file format.
-
- Keyword Args:
- scope (str|list of str): scope(s) of the credentials being
- requested. Defaults to https://www.googleapis.com/auth/userinfo.email.
- service_accounts_creds_root (str or None): location where all service
- account credentials are stored. ``credentials_filename`` is relative
- to this path. None means 'use default location'.
- """
- scope = scope or DEFAULT_SCOPES
- if isinstance(scope, string_types):
- scope = [scope]
- assert all(isinstance(s, string_types) for s in scope)
-
- key = load_service_account_credentials(
- credentials_filename,
- service_accounts_creds_root=service_accounts_creds_root)
-
- return oauth2client.client.SignedJwtAssertionCredentials(
- key['client_email'], key['private_key'], scope)
-
-
-def get_authenticated_http(credentials_filename,
- scope=None,
- service_accounts_creds_root=None,
- http_identifier=None,
- timeout=DEFAULT_TIMEOUT):
- """Creates an httplib2.Http wrapped with a service account authenticator.
-
- Args:
- credentials_filename (str): relative path to the file containing
- credentials in json format. Path is relative to the default
- location where credentials are stored (platform-dependent).
-
- Keyword Args:
- scope (str|list of str): scope(s) of the credentials being
- requested. Defaults to https://www.googleapis.com/auth/userinfo.email.
- service_accounts_creds_root (str or None): location where all service
- account credentials are stored. ``credentials_filename`` is relative
- to this path. None means 'use default location'.
- http_identifier (str): if provided, returns an instrumented http request
- and use this string to identify it to ts_mon.
- timeout (int): timeout passed to httplib2.Http, in seconds.
-
- Returns:
- httplib2.Http authenticated with master's service account.
- """
- creds = get_signed_jwt_assertion_credentials(
- credentials_filename,
- scope=scope,
- service_accounts_creds_root=service_accounts_creds_root)
-
- if http_identifier:
- http = InstrumentedHttp(http_identifier, timeout=timeout)
- else:
- http = httplib2.Http(timeout=timeout)
- return creds.authorize(http)
-
-
class DelegateServiceAccountCredentials(
oauth2client.client.OAuth2Credentials):
"""Authorizes an HTTP client with a service account for which we are an actor.
diff --git a/infra_libs/test/_command_line_linux_test.py b/infra_libs/test/_command_line_linux_test.py
deleted file mode 100644
index cfd9c1d..0000000
--- a/infra_libs/test/_command_line_linux_test.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import sys
-import unittest
-
-from infra_libs import command_line
-
-
-@unittest.skipUnless(sys.platform == 'linux2', 'Only supported on Linux')
-class CommandLineTest(unittest.TestCase):
- @classmethod
- def read_cmdline(cls): # pragma: no cover
- with open('/proc/self/cmdline') as fh:
- return fh.read()
-
- @classmethod
- def setUpClass(cls): # pragma: no cover
- if sys.platform != 'linux2':
- return
-
- cls.original = cls.read_cmdline()
- cls.original_len = len(cls.original)
-
- @classmethod
- def tearDownClass(cls): # pragma: no cover
- if sys.platform != 'linux2':
- return
-
- command_line.set_command_line(cls.original)
-
- def test_set(self): # pragma: no cover
- # Shorter than the original.
- cmdline = 'x' * (self.original_len - 1)
- command_line.set_command_line(cmdline)
- self.assertEqual(cmdline, self.read_cmdline().rstrip('\0'))
-
- # Same length as the original.
- cmdline = 'x' * self.original_len
- command_line.set_command_line(cmdline)
- self.assertEqual(cmdline[:-1], self.read_cmdline().rstrip('\0'))
-
- # Longer than the original.
- cmdline = 'x' * (self.original_len + 1)
- command_line.set_command_line(cmdline)
- self.assertEqual(cmdline[:-2], self.read_cmdline().rstrip('\0'))
diff --git a/infra_libs/test/app_test.py b/infra_libs/test/app_test.py
deleted file mode 100644
index 567f7dc..0000000
--- a/infra_libs/test/app_test.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import argparse
-import unittest
-
-import mock
-
-from infra_libs import app
-from infra_libs import logs
-from infra_libs import ts_mon
-
-
-class MockApplication(app.BaseApplication):
- main = mock.Mock()
-
-
-class AppTest(unittest.TestCase):
- def setUp(self):
- self.mock_logs_process_argparse_options = mock.patch(
- 'infra_libs.logs.process_argparse_options').start()
- self.mock_ts_mon_process_argparse_options = mock.patch(
- 'infra_libs.ts_mon.process_argparse_options').start()
-
- def tearDown(self):
- mock.patch.stopall()
-
- def test_initialises_standard_modules(self):
- with self.assertRaises(SystemExit):
- MockApplication().run(['appname'])
-
- self.mock_logs_process_argparse_options.assert_called_once()
- self.mock_ts_mon_process_argparse_options.assert_called_once()
-
- def test_initialises_standard_modules_except_ts_mon(self):
- class Application(MockApplication):
- USES_TS_MON = False
-
- with self.assertRaises(SystemExit):
- Application().run(['appname'])
-
- self.mock_logs_process_argparse_options.assert_called_once()
- self.assertFalse(self.mock_ts_mon_process_argparse_options.called)
-
- def test_initialises_standard_modules_except_logs(self):
- class Application(MockApplication):
- USES_STANDARD_LOGGING = False
-
- with self.assertRaises(SystemExit):
- Application().run(['appname'])
-
- self.assertFalse(self.mock_logs_process_argparse_options.called)
- self.mock_ts_mon_process_argparse_options.assert_called_once()
-
- def test_argparse_options(self):
- test_case = self
- class App(MockApplication):
- def add_argparse_options(self, p):
- test_case.assertIsInstance(p, argparse.ArgumentParser)
-
- def process_argparse_options(self, o):
- test_case.assertIsInstance(o, argparse.Namespace)
-
- a = App()
- with self.assertRaises(SystemExit):
- a.run(['appname'])
-
- def test_exit_status(self):
- class App(app.BaseApplication):
- def main(self, opts):
- return 42
-
- with self.assertRaises(SystemExit) as cm:
- App().run(['appname'])
- self.assertEqual(42, cm.exception.code)
-
- def test_catches_exceptions(self):
- a = MockApplication()
- a.main.side_effect = Exception
- ts_mon.reset_for_unittest(disable=True)
-
- with self.assertRaises(SystemExit) as cm:
- a.run(['appname'])
- self.assertEqual(1, cm.exception.code)
-
- def test_catches_exceptions_with_ts_mon_disabled(self):
- class Application(MockApplication):
- USES_TS_MON = False
-
- a = Application()
- a.main.side_effect = Exception
- ts_mon.reset_for_unittest(disable=True)
-
- with self.assertRaises(SystemExit) as cm:
- a.run(['appname'])
- self.assertEqual(1, cm.exception.code)
diff --git a/infra_libs/test/data/README.md b/infra_libs/test/data/README.md
index 960100d..ef1964b 100644
--- a/infra_libs/test/data/README.md
+++ b/infra_libs/test/data/README.md
@@ -1,5 +1,2 @@
test_data
=========
-
-*Don't panic*: Note that `valid_creds.json` credentials have been invalidated
-and cannot authenticate.
diff --git a/infra_libs/test/data/creds_malformed.json b/infra_libs/test/data/creds_malformed.json
deleted file mode 100644
index 19ca554..0000000
--- a/infra_libs/test/data/creds_malformed.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKkW4Lk3aRnPYvSU\narK998kFQ9NRauAAj+7PhVxtNjpv8rsQl2FDK/uL2Btt+E5P497pUq5UgjCXa25Y\nI1OVZFjQaf4jqZjs3N8uL+eKsHJpO2GTisOj2moK+7L+yBfM6hC7u0dZ8orfm4Jr\n4LNhpwiQosjEX5oGbAcZ9yse5ivPAgMBAAECgYBTSXKNqM57KRzL7iMUQeBAQvii\nqRLknUJIVi2RVjYE2MmN/OEjxmturvZWpHdPU6ihTvor5nJuLtd69a0I6agQDi0+\n99eWXhQYTpYScEPSifeXm/wctqOtF8XaKXAkjo5dXfs2vYkW5jzEap0DcpFc9fT9\nNbDhI2LkbOIKvdPZoQJBANSwMLAOuk6q+e7d1JGcjtTyQU/2P60rmpBKuQBVgXwp\n7hr+8VhFeJTpKSRgo6Ry3DS/of0l+b61pwo1arMCAn8CQQDLhc1Q6cRhCEQWzScz\nXSCe83EcBIzS49nRH/BM/MwsQ3h4pqocKjF4q++SjsWV6Q19zk0dupEz0JxBOQTy\n4I6xAkEAm+h/+D8DkXFB/zi7fvX9udnPyLbhXKbPCaDM1pLXdVYjRcTG1Acw6i+0\nygbRTlYoV752F2TEG2l7hj879PavLwJBAIYYBosFOupjs9kCGo3xEgkohKHdLZvV\nnDH5RS60cSHI4ps71GDyO94yCosZnn2DK+xz/MNVpU3qaMlgdC5CXkECQQC2JPwz\nk88TwF+Q2ucyGgxTsxx7jZKi8KY+CWDsQx/bNMM5DcGteNlPHtZFYVVgVWHIQed3\nbrQGrLDmBYzvDOJI\n-----END PRIVATE KEY-----\n",
- "client_email": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32@developer.gserviceaccount.com",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com",
-}
diff --git a/infra_libs/test/data/creds_missing_client_email.json b/infra_libs/test/data/creds_missing_client_email.json
deleted file mode 100644
index 5b7a53a..0000000
--- a/infra_libs/test/data/creds_missing_client_email.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKkW4Lk3aRnPYvSU\narK998kFQ9NRauAAj+7PhVxtNjpv8rsQl2FDK/uL2Btt+E5P497pUq5UgjCXa25Y\nI1OVZFjQaf4jqZjs3N8uL+eKsHJpO2GTisOj2moK+7L+yBfM6hC7u0dZ8orfm4Jr\n4LNhpwiQosjEX5oGbAcZ9yse5ivPAgMBAAECgYBTSXKNqM57KRzL7iMUQeBAQvii\nqRLknUJIVi2RVjYE2MmN/OEjxmturvZWpHdPU6ihTvor5nJuLtd69a0I6agQDi0+\n99eWXhQYTpYScEPSifeXm/wctqOtF8XaKXAkjo5dXfs2vYkW5jzEap0DcpFc9fT9\nNbDhI2LkbOIKvdPZoQJBANSwMLAOuk6q+e7d1JGcjtTyQU/2P60rmpBKuQBVgXwp\n7hr+8VhFeJTpKSRgo6Ry3DS/of0l+b61pwo1arMCAn8CQQDLhc1Q6cRhCEQWzScz\nXSCe83EcBIzS49nRH/BM/MwsQ3h4pqocKjF4q++SjsWV6Q19zk0dupEz0JxBOQTy\n4I6xAkEAm+h/+D8DkXFB/zi7fvX9udnPyLbhXKbPCaDM1pLXdVYjRcTG1Acw6i+0\nygbRTlYoV752F2TEG2l7hj879PavLwJBAIYYBosFOupjs9kCGo3xEgkohKHdLZvV\nnDH5RS60cSHI4ps71GDyO94yCosZnn2DK+xz/MNVpU3qaMlgdC5CXkECQQC2JPwz\nk88TwF+Q2ucyGgxTsxx7jZKi8KY+CWDsQx/bNMM5DcGteNlPHtZFYVVgVWHIQed3\nbrQGrLDmBYzvDOJI\n-----END PRIVATE KEY-----\n",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com",
- "type": "service_account"
-}
diff --git a/infra_libs/test/data/creds_missing_private_key.json b/infra_libs/test/data/creds_missing_private_key.json
deleted file mode 100644
index 304e69f..0000000
--- a/infra_libs/test/data/creds_missing_private_key.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "client_email": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32@developer.gserviceaccount.com",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com",
- "type": "service_account"
-}
diff --git a/infra_libs/test/data/creds_missing_type.json b/infra_libs/test/data/creds_missing_type.json
deleted file mode 100644
index 12005a1..0000000
--- a/infra_libs/test/data/creds_missing_type.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKkW4Lk3aRnPYvSU\narK998kFQ9NRauAAj+7PhVxtNjpv8rsQl2FDK/uL2Btt+E5P497pUq5UgjCXa25Y\nI1OVZFjQaf4jqZjs3N8uL+eKsHJpO2GTisOj2moK+7L+yBfM6hC7u0dZ8orfm4Jr\n4LNhpwiQosjEX5oGbAcZ9yse5ivPAgMBAAECgYBTSXKNqM57KRzL7iMUQeBAQvii\nqRLknUJIVi2RVjYE2MmN/OEjxmturvZWpHdPU6ihTvor5nJuLtd69a0I6agQDi0+\n99eWXhQYTpYScEPSifeXm/wctqOtF8XaKXAkjo5dXfs2vYkW5jzEap0DcpFc9fT9\nNbDhI2LkbOIKvdPZoQJBANSwMLAOuk6q+e7d1JGcjtTyQU/2P60rmpBKuQBVgXwp\n7hr+8VhFeJTpKSRgo6Ry3DS/of0l+b61pwo1arMCAn8CQQDLhc1Q6cRhCEQWzScz\nXSCe83EcBIzS49nRH/BM/MwsQ3h4pqocKjF4q++SjsWV6Q19zk0dupEz0JxBOQTy\n4I6xAkEAm+h/+D8DkXFB/zi7fvX9udnPyLbhXKbPCaDM1pLXdVYjRcTG1Acw6i+0\nygbRTlYoV752F2TEG2l7hj879PavLwJBAIYYBosFOupjs9kCGo3xEgkohKHdLZvV\nnDH5RS60cSHI4ps71GDyO94yCosZnn2DK+xz/MNVpU3qaMlgdC5CXkECQQC2JPwz\nk88TwF+Q2ucyGgxTsxx7jZKi8KY+CWDsQx/bNMM5DcGteNlPHtZFYVVgVWHIQed3\nbrQGrLDmBYzvDOJI\n-----END PRIVATE KEY-----\n",
- "client_email": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32@developer.gserviceaccount.com",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com"
-}
diff --git a/infra_libs/test/data/creds_wrong_type.json b/infra_libs/test/data/creds_wrong_type.json
deleted file mode 100644
index 2df0a9d..0000000
--- a/infra_libs/test/data/creds_wrong_type.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKkW4Lk3aRnPYvSU\narK998kFQ9NRauAAj+7PhVxtNjpv8rsQl2FDK/uL2Btt+E5P497pUq5UgjCXa25Y\nI1OVZFjQaf4jqZjs3N8uL+eKsHJpO2GTisOj2moK+7L+yBfM6hC7u0dZ8orfm4Jr\n4LNhpwiQosjEX5oGbAcZ9yse5ivPAgMBAAECgYBTSXKNqM57KRzL7iMUQeBAQvii\nqRLknUJIVi2RVjYE2MmN/OEjxmturvZWpHdPU6ihTvor5nJuLtd69a0I6agQDi0+\n99eWXhQYTpYScEPSifeXm/wctqOtF8XaKXAkjo5dXfs2vYkW5jzEap0DcpFc9fT9\nNbDhI2LkbOIKvdPZoQJBANSwMLAOuk6q+e7d1JGcjtTyQU/2P60rmpBKuQBVgXwp\n7hr+8VhFeJTpKSRgo6Ry3DS/of0l+b61pwo1arMCAn8CQQDLhc1Q6cRhCEQWzScz\nXSCe83EcBIzS49nRH/BM/MwsQ3h4pqocKjF4q++SjsWV6Q19zk0dupEz0JxBOQTy\n4I6xAkEAm+h/+D8DkXFB/zi7fvX9udnPyLbhXKbPCaDM1pLXdVYjRcTG1Acw6i+0\nygbRTlYoV752F2TEG2l7hj879PavLwJBAIYYBosFOupjs9kCGo3xEgkohKHdLZvV\nnDH5RS60cSHI4ps71GDyO94yCosZnn2DK+xz/MNVpU3qaMlgdC5CXkECQQC2JPwz\nk88TwF+Q2ucyGgxTsxx7jZKi8KY+CWDsQx/bNMM5DcGteNlPHtZFYVVgVWHIQed3\nbrQGrLDmBYzvDOJI\n-----END PRIVATE KEY-----\n",
- "client_email": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32@developer.gserviceaccount.com",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com",
- "type": "wrong_type"
-}
diff --git a/infra_libs/test/data/valid_creds.json b/infra_libs/test/data/valid_creds.json
deleted file mode 100644
index 508472a..0000000
--- a/infra_libs/test/data/valid_creds.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "private_key_id": "e41e91c16a6a748b5fe7b0065e54dda48a8c3639",
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKkW4Lk3aRnPYvSU\narK998kFQ9NRauAAj+7PhVxtNjpv8rsQl2FDK/uL2Btt+E5P497pUq5UgjCXa25Y\nI1OVZFjQaf4jqZjs3N8uL+eKsHJpO2GTisOj2moK+7L+yBfM6hC7u0dZ8orfm4Jr\n4LNhpwiQosjEX5oGbAcZ9yse5ivPAgMBAAECgYBTSXKNqM57KRzL7iMUQeBAQvii\nqRLknUJIVi2RVjYE2MmN/OEjxmturvZWpHdPU6ihTvor5nJuLtd69a0I6agQDi0+\n99eWXhQYTpYScEPSifeXm/wctqOtF8XaKXAkjo5dXfs2vYkW5jzEap0DcpFc9fT9\nNbDhI2LkbOIKvdPZoQJBANSwMLAOuk6q+e7d1JGcjtTyQU/2P60rmpBKuQBVgXwp\n7hr+8VhFeJTpKSRgo6Ry3DS/of0l+b61pwo1arMCAn8CQQDLhc1Q6cRhCEQWzScz\nXSCe83EcBIzS49nRH/BM/MwsQ3h4pqocKjF4q++SjsWV6Q19zk0dupEz0JxBOQTy\n4I6xAkEAm+h/+D8DkXFB/zi7fvX9udnPyLbhXKbPCaDM1pLXdVYjRcTG1Acw6i+0\nygbRTlYoV752F2TEG2l7hj879PavLwJBAIYYBosFOupjs9kCGo3xEgkohKHdLZvV\nnDH5RS60cSHI4ps71GDyO94yCosZnn2DK+xz/MNVpU3qaMlgdC5CXkECQQC2JPwz\nk88TwF+Q2ucyGgxTsxx7jZKi8KY+CWDsQx/bNMM5DcGteNlPHtZFYVVgVWHIQed3\nbrQGrLDmBYzvDOJI\n-----END PRIVATE KEY-----\n",
- "client_email": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32@developer.gserviceaccount.com",
- "client_id": "970906992160-mtghjhg8gar32iaum5c6q9demf0nec32.apps.googleusercontent.com",
- "type": "service_account"
-}
\ No newline at end of file
diff --git a/infra_libs/test/httplib2_utils_test.py b/infra_libs/test/httplib2_utils_test.py
index 668d5e5..b4a4bd0 100644
--- a/infra_libs/test/httplib2_utils_test.py
+++ b/infra_libs/test/httplib2_utils_test.py
@@ -18,121 +18,8 @@
import httplib2
import mock
-import oauth2client.client
-DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data')
-
-
-class LoadJsonCredentialsTest(unittest.TestCase):
- # Everything's good, should not raise any exceptions.
- def test_valid_credentials(self):
- creds = httplib2_utils.load_service_account_credentials(
- 'valid_creds.json',
- service_accounts_creds_root=DATA_DIR)
- self.assertIsInstance(creds, dict)
- self.assertIn('type', creds)
- self.assertIn('client_email', creds)
- self.assertIn('private_key', creds)
-
- # File exists but issue with the content: raises AuthError.
- def test_missing_type(self):
- with self.assertRaises(infra_libs.AuthError):
- httplib2_utils.load_service_account_credentials(
- 'creds_missing_type.json',
- service_accounts_creds_root=DATA_DIR)
-
- def test_wrong_type(self):
- with self.assertRaises(infra_libs.AuthError):
- httplib2_utils.load_service_account_credentials(
- 'creds_wrong_type.json',
- service_accounts_creds_root=DATA_DIR)
-
- def test_missing_client_email(self):
- with self.assertRaises(infra_libs.AuthError):
- httplib2_utils.load_service_account_credentials(
- 'creds_missing_client_email.json',
- service_accounts_creds_root=DATA_DIR)
-
- def test_missing_private_key(self):
- with self.assertRaises(infra_libs.AuthError):
- httplib2_utils.load_service_account_credentials(
- 'creds_missing_private_key.json',
- service_accounts_creds_root=DATA_DIR)
-
- def test_malformed(self):
- with self.assertRaises(infra_libs.AuthError):
- httplib2_utils.load_service_account_credentials(
- 'creds_malformed.json',
- service_accounts_creds_root=DATA_DIR)
-
- # Problem with the file itself
- def test_file_not_found(self):
- with self.assertRaises(IOError):
- httplib2_utils.load_service_account_credentials(
- 'this_file_should_not_exist.json',
- service_accounts_creds_root=DATA_DIR)
-
-
-class GetSignedJwtAssertionCredentialsTest(unittest.TestCase):
- def test_valid_credentials(self):
- creds = infra_libs.get_signed_jwt_assertion_credentials(
- 'valid_creds.json',
- service_accounts_creds_root=DATA_DIR)
- self.assertIsInstance(creds,
- oauth2client.client.SignedJwtAssertionCredentials)
- # A default scope must be provided, we don't care which one
- self.assertTrue(creds.scope)
-
- def test_valid_credentials_with_scope_as_string(self):
- creds = infra_libs.get_signed_jwt_assertion_credentials(
- 'valid_creds.json',
- scope='repo',
- service_accounts_creds_root=DATA_DIR)
- self.assertIsInstance(creds,
- oauth2client.client.SignedJwtAssertionCredentials)
- self.assertIn('repo', creds.scope)
-
- def test_valid_credentials_with_scope_as_list(self):
- creds = infra_libs.get_signed_jwt_assertion_credentials(
- 'valid_creds.json',
- scope=['gist'],
- service_accounts_creds_root=DATA_DIR)
- self.assertIsInstance(creds,
- oauth2client.client.SignedJwtAssertionCredentials)
- self.assertIn('gist', creds.scope)
-
- # Only test one malformed case and rely on LoadJsonCredentialsTest
- # for the other cases.
- def test_malformed_credentials(self):
- with self.assertRaises(infra_libs.AuthError):
- infra_libs.get_signed_jwt_assertion_credentials(
- 'creds_malformed.json',
- service_accounts_creds_root=DATA_DIR)
-
-
-class GetAuthenticatedHttp(unittest.TestCase):
- def test_valid_credentials(self):
- http = infra_libs.get_authenticated_http(
- 'valid_creds.json',
- service_accounts_creds_root=DATA_DIR)
- self.assertIsInstance(http, httplib2.Http)
-
- def test_valid_credentials_authenticated(self):
- http = infra_libs.get_authenticated_http(
- 'valid_creds.json',
- service_accounts_creds_root=DATA_DIR,
- http_identifier='test_case')
- self.assertIsInstance(http, infra_libs.InstrumentedHttp)
-
- # Only test one malformed case and rely on LoadJsonCredentialsTest
- # for the other cases.
- def test_malformed_credentials(self):
- with self.assertRaises(infra_libs.AuthError):
- infra_libs.get_authenticated_http(
- 'creds_malformed.json',
- service_accounts_creds_root=DATA_DIR)
-
class RetriableHttplib2Test(unittest.TestCase):
def setUp(self):
super(RetriableHttplib2Test, self).setUp()
@@ -142,13 +29,6 @@
_MOCK_REQUEST = mock.call('http://foo/', 'GET', None)
- def test_authorize(self):
- http = infra_libs.RetriableHttp(httplib2.Http())
- creds = infra_libs.get_signed_jwt_assertion_credentials(
- 'valid_creds.json',
- service_accounts_creds_root=DATA_DIR)
- creds.authorize(http)
-
def test_delegate_get_attr(self):
"""RetriableHttp should delegate getting attribute except request() to
Http"""
diff --git a/infra_libs/test/utils_test.py b/infra_libs/test/utils_test.py
index 60e242e..65222ae 100644
--- a/infra_libs/test/utils_test.py
+++ b/infra_libs/test/utils_test.py
@@ -155,18 +155,3 @@
# And everything should have been cleaned up afterward
self.assertFalse(os.path.isdir(tempdir))
-
-
-class RmtreeTest(unittest.TestCase):
- def test_rmtree_directory(self):
- with infra_libs.temporary_directory() as tempdir:
- infra_libs.rmtree(tempdir)
- self.assertFalse(os.path.exists(tempdir))
-
- def test_rmtree_file(self):
- with infra_libs.temporary_directory() as tempdir:
- tmpfile = os.path.join(tempdir, 'foo')
- with open(tmpfile, 'w') as f:
- f.write('asdfasdf')
- infra_libs.rmtree(tmpfile)
- self.assertFalse(os.path.exists(tmpfile))
diff --git a/infra_libs/utils.py b/infra_libs/utils.py
index 3353e83..0c40989 100644
--- a/infra_libs/utils.py
+++ b/infra_libs/utils.py
@@ -9,14 +9,10 @@
import contextlib
import datetime
-import errno
import json
-import os
import shutil
-import subprocess
import sys
import tempfile
-import time
from six import text_type, PY2
@@ -124,95 +120,6 @@
return to_utf8(obj) if PY2 else obj
-# TODO(hinoka): Add tests crbug.com/500781
-def rmtree(file_path): # pragma: no cover
- """Recursively removes a directory, even if it's marked read-only.
-
- Remove the directory located at file_path, if it exists.
-
- shutil.rmtree() doesn't work on Windows if any of the files or directories
- are read-only, which svn repositories and some .svn files are. We need to
- be able to force the files to be writable (i.e., deletable) as we traverse
- the tree.
-
- Even with all this, Windows still sometimes fails to delete a file, citing
- a permission error (maybe something to do with antivirus scans or disk
- indexing). The best suggestion any of the user forums had was to wait a
- bit and try again, so we do that too. It's hand-waving, but sometimes it
- works. :/
- """
- if not os.path.exists(file_path):
- return
-
- if os.path.isfile(file_path):
- for i in range(3):
- try:
- os.remove(file_path)
- return
- except OSError:
- if i == 2:
- raise
- time.sleep(3)
-
- if sys.platform == 'win32':
- # Give up and use cmd.exe's rd command.
- file_path = os.path.normcase(file_path)
- for i in range(3):
- try:
- subprocess.check_call(['cmd.exe', '/c', 'rd', '/q', '/s', file_path])
- return
- except subprocess.CalledProcessError:
- if i == 2:
- raise
- time.sleep(3)
-
- def remove_with_retry(rmfunc, path):
- if os.path.islink(path):
- return os.remove(path)
- else:
- return rmfunc(path)
-
- def rmtree_on_error(function, _, excinfo):
- """This works around a problem whereby python 2.x on Windows has no ability
- to check for symbolic links. os.path.islink always returns False. But
- shutil.rmtree will fail if invoked on a symbolic link whose target was
- deleted before the link. E.g., reproduce like this:
- > mkdir test
- > mkdir test\1
- > mklink /D test\current test\1
- > python -c "import infra_libs; infra_libs.rmtree('test')"
- To avoid this issue, we pass this error-handling function to rmtree. If
- we see the exact sort of failure, we ignore it. All other failures we re-
- raise.
- """
-
- exception_type = excinfo[0]
- exception_value = excinfo[1]
- # If shutil.rmtree encounters a symbolic link on Windows, os.listdir will
- # fail with a WindowsError exception with an ENOENT errno (i.e., file not
- # found). We'll ignore that error. Note that WindowsError is not defined
- # for non-Windows platforms, so we use OSError (of which it is a subclass)
- # to avoid lint complaints about an undefined global on non-Windows
- # platforms.
- if (function is os.listdir) and issubclass(exception_type, OSError):
- if exception_value.errno != errno.ENOENT:
- raise
- else:
- raise
-
- for root, dirs, files in os.walk(file_path, topdown=False):
- # For POSIX: making the directory writable guarantees removability.
- # Windows will ignore the non-read-only bits in the chmod value.
- os.chmod(root, 0o770)
- for name in files:
- remove_with_retry(os.remove, os.path.join(root, name))
- for name in dirs:
- remove_with_retry(lambda p: shutil.rmtree(p, onerror=rmtree_on_error),
- os.path.join(root, name))
-
- remove_with_retry(os.rmdir, file_path)
-
-
# We're trying to be compatible with Python3 tempfile.TemporaryDirectory
# context manager here. And they used 'dir' as a keyword argument.
# pylint: disable=redefined-builtin