From 6c953a414f2b8ddb0ba489b6b43b4fea73e9c529 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Mar 29 2018 14:54:02 +0000 Subject: consolidate ConfigParser usage Fixes: https://pagure.io/koji/issue/865 --- diff --git a/builder/kojid b/builder/kojid index 726d535..8cf130c 100755 --- a/builder/kojid +++ b/builder/kojid @@ -56,7 +56,7 @@ import xmlrpclib import zipfile import copy import Cheetah.Template -from ConfigParser import ConfigParser +from ConfigParser import SafeConfigParser from fnmatch import fnmatch from gzip import GzipFile from optparse import OptionParser, SUPPRESS_HELP @@ -5610,7 +5610,7 @@ def get_options(): assert False # pragma: no cover # load local config - config = ConfigParser() + config = SafeConfigParser() config.read(options.configFile) for x in config.sections(): if x != 'kojid': diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py index a6f338a..7c3117b 100644 --- a/cli/koji_cli/commands.py +++ b/cli/koji_cli/commands.py @@ -5645,10 +5645,8 @@ def handle_image_build(options, session, args): if not os.path.exists(task_options.config): parser.error(_("%s not found!" % task_options.config)) section = 'image-build' - config = six.moves.configparser.ConfigParser() - conf_fd = open(task_options.config) - config.readfp(conf_fd) - conf_fd.close() + config = six.moves.configparser.SafeConfigParser() + config.read(task_options.config) if not config.has_section(section): parser.error(_("single section called [%s] is required" % section)) # pluck out the positional arguments first diff --git a/hub/kojixmlrpc.py b/hub/kojixmlrpc.py index f518da8..677bd44 100644 --- a/hub/kojixmlrpc.py +++ b/hub/kojixmlrpc.py @@ -18,7 +18,7 @@ # Authors: # Mike McLean -from ConfigParser import RawConfigParser +from ConfigParser import SafeConfigParser import datetime import inspect import logging @@ -381,16 +381,11 @@ def load_config(environ): """ logger = logging.getLogger("koji") #get our config file(s) - cf = environ.get('koji.hub.ConfigFile', '/etc/koji-hub/hub.conf') - cfdir = environ.get('koji.hub.ConfigDir', '/etc/koji-hub/hub.conf.d') - if cfdir: - configs = koji.config_directory_contents(cfdir) - else: - configs = [] - if cf and os.path.isfile(cf): - configs.append(cf) + cfs = [environ.get('koji.hub.ConfigFile', '/etc/koji-hub/hub.conf')] or [] + cfdirs = [environ.get('koji.hub.ConfigDir', '/etc/koji-hub/hub.conf.d')] or [] + configs = koji.get_config_files(cfdirs, cfs) if configs: - config = RawConfigParser() + config = SafeConfigParser() config.read(configs) else: config = None diff --git a/koji/__init__.py b/koji/__init__.py index 24347bd..bff082f 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -1630,6 +1630,34 @@ def config_directory_contents(dir_name): return configs +def get_config_files(dirs=None, files=None, strict=False): + # get list of config files in given directories and files, order is + # preserved + configs = [] + if dirs is not None: + for d in dirs: + cfgs = config_directory_contents(d) + if cfgs: + configs.extend(cfgs) + else: + logging.debug("No config files found in directory: %s" % d) + if files is not None: + configs += files + + # check access + result = [] + for f in configs: + if os.path.isfile(f) and os.access(f, os.F_OK): + result.append(f) + else: + if strict: + raise ConfigurationError("Config file %s can't be opened." % f) + else: + logging.warn("Config file %s can't be opened." % f) + + return result + + def read_config(profile_name, user_config=None): config_defaults = { 'server' : 'http://localhost/kojihub', @@ -1667,42 +1695,25 @@ def read_config(profile_name, user_config=None): #note: later config files override earlier ones # /etc/koji.conf.d - configs = config_directory_contents('/etc/koji.conf.d') - - # /etc/koji.conf - if os.access('/etc/koji.conf', os.F_OK): - configs.append('/etc/koji.conf') + config_dirs = ['/etc/koji.conf.d'] + config_files = ['/etc/koji.conf'] # User specific configuration if user_config: # Config file specified on command line - fn = os.path.expanduser(user_config) - if os.path.isdir(fn): - # Specified config is a directory - contents = config_directory_contents(fn) - if not contents: - raise ConfigurationError("No config files found in directory: %s" % fn) - configs.extend(contents) - else: - # Specified config is a file - if not os.access(fn, os.F_OK): - raise ConfigurationError("No such file: %s" % fn) - configs.append(fn) + config_dirs.append(os.path.expanduser(user_config)) else: # User config - user_config_dir = os.path.expanduser("~/.koji/config.d") - configs.extend(config_directory_contents(user_config_dir)) - fn = os.path.expanduser("~/.koji/config") - if os.access(fn, os.F_OK): - configs.append(fn) + config_dirs.append(os.path.expanduser("~/.koji/config.d")) + config_files.append(os.path.expanduser("~/.koji/config")) + + configs = get_config_files(dirs=config_dirs, files=config_files) # Load the configs in a particular order got_conf = False for configFile in configs: - f = open(configFile) - config = six.moves.configparser.ConfigParser() - config.readfp(f) - f.close() + config = six.moves.configparser.SafeConfigParser() + config.read(configFile) if config.has_section(profile_name): got_conf = True for name, value in config.items(profile_name): diff --git a/koji/util.py b/koji/util.py index eaf7813..f34b6d1 100644 --- a/koji/util.py +++ b/koji/util.py @@ -667,11 +667,9 @@ def parse_maven_params(confs, chain=False, scratch=False): """ if not isinstance(confs, (list, tuple)): confs = [confs] - config = six.moves.configparser.ConfigParser() - for conf in confs: - conf_fd = open(conf) - config.readfp(conf_fd) - conf_fd.close() + configs = koji.get_config_files(files=confs) + config = six.moves.configparser.SafeConfigParser() + config.read(configs) builds = {} for package in config.sections(): buildtype = 'maven' diff --git a/plugins/hub/protonmsg.py b/plugins/hub/protonmsg.py index 85165ba..08f84ea 100644 --- a/plugins/hub/protonmsg.py +++ b/plugins/hub/protonmsg.py @@ -270,8 +270,7 @@ def send_queued_msgs(cbtype, *args, **kws): global CONFIG if not CONFIG: conf = ConfigParser.SafeConfigParser() - with open(CONFIG_FILE) as conffile: - conf.readfp(conffile) + conf.read(CONFIG_FILE) CONFIG = conf urls = CONFIG.get('broker', 'urls').split() test_mode = False diff --git a/plugins/hub/rpm2maven.py b/plugins/hub/rpm2maven.py index ad78b8f..bcb8448 100644 --- a/plugins/hub/rpm2maven.py +++ b/plugins/hub/rpm2maven.py @@ -12,7 +12,6 @@ from koji.util import rmtree import ConfigParser import fnmatch import os -import shutil import subprocess CONFIG_FILE = '/etc/koji-hub/plugins/rpm2maven.conf' diff --git a/tests/test_cli/test_image_build.py b/tests/test_cli/test_image_build.py index e1e0f10..1e9de92 100644 --- a/tests/test_cli/test_image_build.py +++ b/tests/test_cli/test_image_build.py @@ -213,10 +213,10 @@ class TestImageBuild(utils.CliTestCase): return self.custom_os_path_exists[filepath] return self.os_path_exists(filepath) - def mock_builtin_open(self, filepath, *args): + def mock_builtin_open(self, filepath, *args, **kwargs): if filepath in self.custom_open: return self.custom_open[filepath] - return self.builtin_open(filepath, *args) + return self.builtin_open(filepath, *args, **kwargs) def setUp(self): self.os_path_exists = os.path.exists @@ -307,12 +307,14 @@ factory_test_ver=1.0 """ self.custom_open[config_file] = six.StringIO(fake_config) - with mock.patch('os.path.exists', new=self.mock_os_path_exists), \ - mock.patch('koji_cli.commands.open', new=self.mock_builtin_open): - handle_image_build( - self.options, - self.session, - ['--config', config_file]) + if six.PY2: + with mock.patch('os.path.exists', new=self.mock_os_path_exists), \ + mock.patch('__builtin__.open', new=self.mock_builtin_open): + handle_image_build(self.options, self.session, ['--config', config_file]) + else: + with mock.patch('os.path.exists', new=self.mock_os_path_exists), \ + mock.patch('builtins.open', new=self.mock_builtin_open): + handle_image_build(self.options, self.session, ['--config', config_file]) args, kwargs = build_image_oz_mock.call_args self.assertDictEqual(TASK_OPTIONS, args[1].__dict__) diff --git a/tests/test_lib/test_profiles.py b/tests/test_lib/test_profiles.py index 0417023..4c23aec 100644 --- a/tests/test_lib/test_profiles.py +++ b/tests/test_lib/test_profiles.py @@ -40,6 +40,3 @@ def stress(errors, n): return else: errors[n] = None - - - diff --git a/tests/test_lib/test_utils.py b/tests/test_lib/test_utils.py index 226534a..4fd3819 100644 --- a/tests/test_lib/test_utils.py +++ b/tests/test_lib/test_utils.py @@ -487,7 +487,7 @@ class MavenUtilTestCase(unittest.TestCase): self.assertEqual(cm.exception.args[0], 'total ordering not possible') def _read_conf(self, cfile): - config = six.moves.configparser.ConfigParser() + config = six.moves.configparser.SafeConfigParser() path = os.path.dirname(__file__) with open(path + cfile, 'r') as conf_file: config.readfp(conf_file) diff --git a/util/koji-gc b/util/koji-gc index 89cc492..6675000 100755 --- a/util/koji-gc +++ b/util/koji-gc @@ -114,21 +114,14 @@ def get_options(): defaults = parser.get_default_values() - config = ConfigParser.ConfigParser() - cf = getattr(options, 'config_file', None) - if cf: - if not os.access(cf, os.F_OK): - parser.error(_("No such file: %s") % cf) - assert False # pragma: no cover - else: - cf = '/etc/koji-gc/koji-gc.conf' - if not os.access(cf, os.F_OK): - cf = None - if not cf: + config = ConfigParser.SafeConfigParser() + cf = getattr(options, 'config_file', '/etc/koji-gc/koji-gc.conf') + configs = koji.get_config_files(files=[cf]) + if not configs: print("no config file") config = None else: - config.read(cf) + config.read(configs) # List of values read from config file to update default parser values cfgmap = [ # name, alias, type diff --git a/util/koji-shadow b/util/koji-shadow index a958c9c..6a2ae3d 100755 --- a/util/koji-shadow +++ b/util/koji-shadow @@ -160,21 +160,14 @@ def get_options(): (options, args) = parser.parse_args() defaults = parser.get_default_values() - config = ConfigParser.ConfigParser() - cf = getattr(options, 'config_file', None) - if cf: - if not os.access(cf, os.F_OK): - parser.error(_("No such file: %s") % cf) - assert False # pragma: no cover - else: - cf = '/etc/koji-shadow/koji-shadow.conf' - if not os.access(cf, os.F_OK): - cf = None - if not cf: + config = ConfigParser.SafeConfigParser() + cf = getattr(options, 'config_file', '/etc/koji-shadow/koji-shadow.conf') + configs = koji.get_config_files(files=[cf]) + if not configs: log("no config file") config = None else: - config.read(cf) + config.read(configs) #allow config file to update defaults for opt in parser.option_list: if not opt.dest: diff --git a/util/kojira b/util/kojira index bf19894..32f5e9d 100755 --- a/util/kojira +++ b/util/kojira @@ -25,7 +25,7 @@ import os import koji from koji.util import rmtree, parseStatus from optparse import OptionParser -from ConfigParser import ConfigParser +from ConfigParser import SafeConfigParser import errno import logging import logging.handlers @@ -811,7 +811,7 @@ def get_options(): parser.add_option("--logfile", help="Specify logfile") (options, args) = parser.parse_args() - config = ConfigParser() + config = SafeConfigParser() config.read(options.configFile) section = 'kojira' for x in config.sections(): diff --git a/vm/kojikamid.py b/vm/kojikamid.py index 1d40e68..6412e37 100755 --- a/vm/kojikamid.py +++ b/vm/kojikamid.py @@ -27,7 +27,7 @@ # in a cygwin shell. from optparse import OptionParser -from ConfigParser import ConfigParser +from ConfigParser import SafeConfigParser import os import subprocess import sys @@ -201,7 +201,7 @@ class WindowsBuild(object): elif len(specfiles) > 1: raise BuildError('Multiple .ini files found') - conf = ConfigParser() + conf = SafeConfigParser() conf.read(os.path.join(self.spec_dir, specfiles[0])) # [naming] section diff --git a/vm/kojivmd b/vm/kojivmd index 41789ec..fe3f489 100755 --- a/vm/kojivmd +++ b/vm/kojivmd @@ -42,7 +42,7 @@ import base64 import pwd import requests import fnmatch -from ConfigParser import ConfigParser +from ConfigParser import SafeConfigParser from contextlib import closing from optparse import OptionParser try: @@ -98,7 +98,7 @@ def get_options(): assert False # pragma: no cover # load local config - config = ConfigParser() + config = SafeConfigParser() config.read(options.configFile) for x in config.sections(): if x != 'kojivmd': diff --git a/www/kojiweb/wsgi_publisher.py b/www/kojiweb/wsgi_publisher.py index 778d992..1ed6ee4 100644 --- a/www/kojiweb/wsgi_publisher.py +++ b/www/kojiweb/wsgi_publisher.py @@ -29,7 +29,7 @@ import pprint import sys import traceback -from ConfigParser import RawConfigParser +from ConfigParser import SafeConfigParser from koji.server import ServerError, ServerRedirect from koji.util import dslice @@ -123,16 +123,11 @@ class Dispatcher(object): - all PythonOptions (except koji.web.ConfigFile) are now deprecated and support for them will disappear in a future version of Koji """ - cf = environ.get('koji.web.ConfigFile', '/etc/kojiweb/web.conf') - cfdir = environ.get('koji.web.ConfigDir', '/etc/kojiweb/web.conf.d') - if cfdir: - configs = koji.config_directory_contents(cfdir) - else: - configs = [] - if cf and os.path.isfile(cf): - configs.append(cf) + cfs = [environ.get('koji.web.ConfigFile', '/etc/kojiweb/web.conf')] or [] + cfdirs = [environ.get('koji.web.ConfigDir', '/etc/kojiweb/web.conf.d')] or []] + configs = koji.get_config_files(dirs=cfdirs, files=cfs) if configs: - config = RawConfigParser() + config = SafeConfigParser() config.read(configs) else: raise koji.GenericError("Configuration missing")