We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Config module 'imp' deprecation warning
Currently, the config module uses a deprecated library method to load the config file into a module which causes a DeprecationWarning

```============================================= warnings summary =============================================
turbinia/config/__init__.py:19
  /workspaces/turbinia/turbinia/config/__init__.py:19: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
    import imp
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `turbinia/config/__init__.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 2016 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Basic Turbinia config."""
16 
17 from __future__ import unicode_literals
18 
19 import imp
20 import itertools
21 import logging
22 import os
23 import sys
24 
25 from turbinia import TurbiniaException
26 
27 DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
28 
29 # Look for config files with these names
30 CONFIGFILES = ['.turbiniarc', 'turbinia.conf', 'turbinia_config_tmpl.py']
31 # Look in homedir first, then /etc/turbinia
32 CONFIGPATH = [
33     os.path.expanduser('~'),
34     '/etc/turbinia',
35     os.path.dirname(os.path.abspath(__file__)),
36 ]
37 # Config setup reminder for cleaner error handling on empty configs.
38 CONFIG_MSG = (
39     'Copy turbinia/config/turbinia_config_tmpl.py to ~/.turbiniarc '
40     'or /etc/turbinia/turbinia.conf, edit, and re-run.')
41 
42 # Required config vars
43 REQUIRED_VARS = [
44     # Turbinia Config
45     'INSTANCE_ID',
46     'STATE_MANAGER',
47     'TASK_MANAGER',
48     'LOG_DIR',
49     'LOCK_FILE',
50     'TMP_RESOURCE_DIR',
51     'RESOURCE_FILE',
52     'RESOURCE_FILE_LOCK',
53     'SCALEDOWN_WORKER_FILE',
54     'OUTPUT_DIR',
55     'TMP_DIR',
56     'SLEEP_TIME',
57     'SINGLE_RUN',
58     'MOUNT_DIR_PREFIX',
59     'SHARED_FILESYSTEM',
60     'DEBUG_TASKS',
61     'DEPENDENCIES',
62     'DOCKER_ENABLED',
63     'DISABLED_JOBS',
64 ]
65 
66 # Optional config vars.  Some may be mandatory depending on the configuration
67 # (e.g. if TASK_MANAGER is set to 'PSQ', then the GCE Config variables are
68 # required), but these requirements are not enforced.
69 OPTIONAL_VARS = [
70     # GCE CONFIG
71     'TURBINIA_PROJECT',
72     'TURBINIA_ZONE',
73     'TURBINIA_REGION',
74     'BUCKET_NAME',
75     'PSQ_TOPIC',
76     'PUBSUB_TOPIC',
77     'GCS_OUTPUT_PATH',
78     'RECIPE_FILE_DIR',
79     'STACKDRIVER_LOGGING',
80     'STACKDRIVER_TRACEBACK',
81     # REDIS CONFIG
82     'REDIS_HOST',
83     'REDIS_PORT',
84     'REDIS_DB',
85     # Celery config
86     'CELERY_BROKER',
87     'CELERY_BACKEND',
88     'KOMBU_BROKER',
89     'KOMBU_CHANNEL',
90     'KOMBU_DURABLE',
91     # Email config
92     'EMAIL_NOTIFICATIONS',
93     'EMAIL_HOST_ADDRESS',
94     'EMAIL_PORT',
95     'EMAIL_ADDRESS',
96     'EMAIL_PASSWORD',
97     # Prometheus config
98     'PROMETHEUS_ENABLED',
99     'PROMETHEUS_ADDR',
100     'PROMETHEUS_PORT',
101     # dfDewey config
102     'DFDEWEY_PG_HOST',
103     'DFDEWEY_PG_PORT',
104     'DFDEWEY_PG_DB_NAME',
105     'DFDEWEY_OS_HOST',
106     'DFDEWEY_OS_PORT',
107     'DFDEWEY_OS_URL',
108     # General config
109     'TURBINIA_COMMAND'
110 ]
111 
112 # Environment variable to look for path data in
113 ENVCONFIGVAR = 'TURBINIA_CONFIG_PATH'
114 
115 CONFIG = None
116 
117 log = logging.getLogger('turbinia')
118 
119 
120 def LoadConfig(config_file=None):
121   """Finds Turbinia config file and loads it.
122 
123   Args:
124     config_file(str): full path to config file
125   """
126   # TODO(aarontp): Find way to not require global var here.  Maybe a singleton
127   # pattern on the config class.
128   # pylint: disable=global-statement
129   global CONFIG
130   if CONFIG and not config_file:
131     log.debug(
132         'Returning cached config from {0:s} instead of reloading config'.format(
133             CONFIG.configSource))
134     return CONFIG
135 
136   if not config_file:
137     log.debug('No config specified. Looking in default locations for config.')
138     # If the environment variable is set, take precedence over the pre-defined
139     # CONFIGPATHs.
140     configpath = CONFIGPATH
141     if ENVCONFIGVAR in os.environ:
142       configpath = os.environ[ENVCONFIGVAR].split(':')
143 
144     # Load first file found
145     for _dir, _file in itertools.product(configpath, CONFIGFILES):
146       if os.path.exists(os.path.join(_dir, _file)):
147         config_file = os.path.join(_dir, _file)
148         break
149 
150   if config_file is None:
151     raise TurbiniaException('No config files found')
152 
153   log.debug('Loading config from {0:s}'.format(config_file))
154   # Warn about using fallback source config, but it's currently necessary for
155   # tests. See issue #446.
156   if 'turbinia_config_tmpl' in config_file:
157     log.warning('Using fallback source config. {0:s}'.format(CONFIG_MSG))
158   try:
159     _config = imp.load_source('config', config_file)
160   except IOError as exception:
161     message = (
162         'Could not load config file {0:s}: {1!s}'.format(
163             config_file, exception))
164     log.error(message)
165     raise TurbiniaException(message)
166 
167   _config.configSource = config_file
168   ValidateAndSetConfig(_config)
169 
170   # Set the environment var for this so that we don't see the "No project ID
171   # could be determined." warning later.
172   if hasattr(_config, 'TURBINIA_PROJECT') and _config.TURBINIA_PROJECT:
173     os.environ['GOOGLE_CLOUD_PROJECT'] = _config.TURBINIA_PROJECT
174 
175   CONFIG = _config
176   log.debug(
177       'Returning parsed config loaded from {0:s}'.format(CONFIG.configSource))
178   return _config
179 
180 
181 def ValidateAndSetConfig(_config):
182   """Makes sure that the config has the vars loaded and set in the module."""
183   # Explicitly set the config path
184   setattr(sys.modules[__name__], 'configSource', _config.configSource)
185 
186   CONFIGVARS = REQUIRED_VARS + OPTIONAL_VARS
187   for var in CONFIGVARS:
188     empty_value = False
189     if not hasattr(_config, var):
190       if var in OPTIONAL_VARS:
191         log.debug(
192             'Setting non-existent but optional config variable {0:s} to '
193             'None'.format(var))
194         empty_value = True
195       else:
196         raise TurbiniaException(
197             'Required config attribute {0:s}:{1:s} not in config'.format(
198                 _config.configSource, var))
199     if var in REQUIRED_VARS and getattr(_config, var) is None:
200       raise TurbiniaException(
201           'Config attribute {0:s}:{1:s} is not set'.format(
202               _config.configSource, var))
203 
204     # Set the attribute in the current module
205     if empty_value:
206       setattr(sys.modules[__name__], var, None)
207     else:
208       setattr(sys.modules[__name__], var, getattr(_config, var))
209 
210 
211 def ParseDependencies():
212   """Parses the config file DEPENDENCIES variable.
213 
214   Raises:
215     TurbiniaException: If bad config file.
216 
217   Returns:
218    dependencies(dict): The parsed dependency values.
219   """
220   dependencies = {}
221   try:
222     for values in CONFIG.DEPENDENCIES:
223       job = values['job'].lower()
224       dependencies[job] = {}
225       dependencies[job]['programs'] = values['programs']
226       dependencies[job]['docker_image'] = values.get('docker_image')
227       dependencies[job]['timeout'] = values.get('timeout')
228   except (KeyError, TypeError) as exception:
229     raise TurbiniaException(
230         'An issue has occurred while parsing the '
231         'dependency config: {0!s}'.format(exception))
232   return dependencies
233
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/turbinia/config/__init__.py b/turbinia/config/__init__.py
--- a/turbinia/config/__init__.py
+++ b/turbinia/config/__init__.py
@@ -16,12 +16,12 @@
 
 from __future__ import unicode_literals
 
-import imp
+import importlib.util
+import importlib.machinery
 import itertools
 import logging
 import os
 import sys
-
 from turbinia import TurbiniaException
 
 DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
@@ -156,7 +156,11 @@
   if 'turbinia_config_tmpl' in config_file:
     log.warning('Using fallback source config. {0:s}'.format(CONFIG_MSG))
   try:
-    _config = imp.load_source('config', config_file)
+    config_loader = importlib.machinery.SourceFileLoader('config', config_file)
+    config_spec = importlib.util.spec_from_loader(
+        config_loader.name, config_loader)
+    _config = importlib.util.module_from_spec(config_spec)
+    config_loader.exec_module(_config)
   except IOError as exception:
     message = (
         'Could not load config file {0:s}: {1!s}'.format(

{"golden_diff": "diff --git a/turbinia/config/__init__.py b/turbinia/config/__init__.py\n--- a/turbinia/config/__init__.py\n+++ b/turbinia/config/__init__.py\n@@ -16,12 +16,12 @@\n \n from __future__ import unicode_literals\n \n-import imp\n+import importlib.util\n+import importlib.machinery\n import itertools\n import logging\n import os\n import sys\n-\n from turbinia import TurbiniaException\n \n DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'\n@@ -156,7 +156,11 @@\n   if 'turbinia_config_tmpl' in config_file:\n     log.warning('Using fallback source config. {0:s}'.format(CONFIG_MSG))\n   try:\n-    _config = imp.load_source('config', config_file)\n+    config_loader = importlib.machinery.SourceFileLoader('config', config_file)\n+    config_spec = importlib.util.spec_from_loader(\n+        config_loader.name, config_loader)\n+    _config = importlib.util.module_from_spec(config_spec)\n+    config_loader.exec_module(_config)\n   except IOError as exception:\n     message = (\n         'Could not load config file {0:s}: {1!s}'.format(\n", "issue": "Config module 'imp' deprecation warning\nCurrently, the config module uses a deprecated library method to load the config file into a module which causes a DeprecationWarning\r\n\r\n```============================================= warnings summary =============================================\r\nturbinia/config/__init__.py:19\r\n  /workspaces/turbinia/turbinia/config/__init__.py:19: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses\r\n    import imp\r\n```\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2016 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Basic Turbinia config.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport imp\nimport itertools\nimport logging\nimport os\nimport sys\n\nfrom turbinia import TurbiniaException\n\nDATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'\n\n# Look for config files with these names\nCONFIGFILES = ['.turbiniarc', 'turbinia.conf', 'turbinia_config_tmpl.py']\n# Look in homedir first, then /etc/turbinia\nCONFIGPATH = [\n    os.path.expanduser('~'),\n    '/etc/turbinia',\n    os.path.dirname(os.path.abspath(__file__)),\n]\n# Config setup reminder for cleaner error handling on empty configs.\nCONFIG_MSG = (\n    'Copy turbinia/config/turbinia_config_tmpl.py to ~/.turbiniarc '\n    'or /etc/turbinia/turbinia.conf, edit, and re-run.')\n\n# Required config vars\nREQUIRED_VARS = [\n    # Turbinia Config\n    'INSTANCE_ID',\n    'STATE_MANAGER',\n    'TASK_MANAGER',\n    'LOG_DIR',\n    'LOCK_FILE',\n    'TMP_RESOURCE_DIR',\n    'RESOURCE_FILE',\n    'RESOURCE_FILE_LOCK',\n    'SCALEDOWN_WORKER_FILE',\n    'OUTPUT_DIR',\n    'TMP_DIR',\n    'SLEEP_TIME',\n    'SINGLE_RUN',\n    'MOUNT_DIR_PREFIX',\n    'SHARED_FILESYSTEM',\n    'DEBUG_TASKS',\n    'DEPENDENCIES',\n    'DOCKER_ENABLED',\n    'DISABLED_JOBS',\n]\n\n# Optional config vars.  Some may be mandatory depending on the configuration\n# (e.g. if TASK_MANAGER is set to 'PSQ', then the GCE Config variables are\n# required), but these requirements are not enforced.\nOPTIONAL_VARS = [\n    # GCE CONFIG\n    'TURBINIA_PROJECT',\n    'TURBINIA_ZONE',\n    'TURBINIA_REGION',\n    'BUCKET_NAME',\n    'PSQ_TOPIC',\n    'PUBSUB_TOPIC',\n    'GCS_OUTPUT_PATH',\n    'RECIPE_FILE_DIR',\n    'STACKDRIVER_LOGGING',\n    'STACKDRIVER_TRACEBACK',\n    # REDIS CONFIG\n    'REDIS_HOST',\n    'REDIS_PORT',\n    'REDIS_DB',\n    # Celery config\n    'CELERY_BROKER',\n    'CELERY_BACKEND',\n    'KOMBU_BROKER',\n    'KOMBU_CHANNEL',\n    'KOMBU_DURABLE',\n    # Email config\n    'EMAIL_NOTIFICATIONS',\n    'EMAIL_HOST_ADDRESS',\n    'EMAIL_PORT',\n    'EMAIL_ADDRESS',\n    'EMAIL_PASSWORD',\n    # Prometheus config\n    'PROMETHEUS_ENABLED',\n    'PROMETHEUS_ADDR',\n    'PROMETHEUS_PORT',\n    # dfDewey config\n    'DFDEWEY_PG_HOST',\n    'DFDEWEY_PG_PORT',\n    'DFDEWEY_PG_DB_NAME',\n    'DFDEWEY_OS_HOST',\n    'DFDEWEY_OS_PORT',\n    'DFDEWEY_OS_URL',\n    # General config\n    'TURBINIA_COMMAND'\n]\n\n# Environment variable to look for path data in\nENVCONFIGVAR = 'TURBINIA_CONFIG_PATH'\n\nCONFIG = None\n\nlog = logging.getLogger('turbinia')\n\n\ndef LoadConfig(config_file=None):\n  \"\"\"Finds Turbinia config file and loads it.\n\n  Args:\n    config_file(str): full path to config file\n  \"\"\"\n  # TODO(aarontp): Find way to not require global var here.  Maybe a singleton\n  # pattern on the config class.\n  # pylint: disable=global-statement\n  global CONFIG\n  if CONFIG and not config_file:\n    log.debug(\n        'Returning cached config from {0:s} instead of reloading config'.format(\n            CONFIG.configSource))\n    return CONFIG\n\n  if not config_file:\n    log.debug('No config specified. Looking in default locations for config.')\n    # If the environment variable is set, take precedence over the pre-defined\n    # CONFIGPATHs.\n    configpath = CONFIGPATH\n    if ENVCONFIGVAR in os.environ:\n      configpath = os.environ[ENVCONFIGVAR].split(':')\n\n    # Load first file found\n    for _dir, _file in itertools.product(configpath, CONFIGFILES):\n      if os.path.exists(os.path.join(_dir, _file)):\n        config_file = os.path.join(_dir, _file)\n        break\n\n  if config_file is None:\n    raise TurbiniaException('No config files found')\n\n  log.debug('Loading config from {0:s}'.format(config_file))\n  # Warn about using fallback source config, but it's currently necessary for\n  # tests. See issue #446.\n  if 'turbinia_config_tmpl' in config_file:\n    log.warning('Using fallback source config. {0:s}'.format(CONFIG_MSG))\n  try:\n    _config = imp.load_source('config', config_file)\n  except IOError as exception:\n    message = (\n        'Could not load config file {0:s}: {1!s}'.format(\n            config_file, exception))\n    log.error(message)\n    raise TurbiniaException(message)\n\n  _config.configSource = config_file\n  ValidateAndSetConfig(_config)\n\n  # Set the environment var for this so that we don't see the \"No project ID\n  # could be determined.\" warning later.\n  if hasattr(_config, 'TURBINIA_PROJECT') and _config.TURBINIA_PROJECT:\n    os.environ['GOOGLE_CLOUD_PROJECT'] = _config.TURBINIA_PROJECT\n\n  CONFIG = _config\n  log.debug(\n      'Returning parsed config loaded from {0:s}'.format(CONFIG.configSource))\n  return _config\n\n\ndef ValidateAndSetConfig(_config):\n  \"\"\"Makes sure that the config has the vars loaded and set in the module.\"\"\"\n  # Explicitly set the config path\n  setattr(sys.modules[__name__], 'configSource', _config.configSource)\n\n  CONFIGVARS = REQUIRED_VARS + OPTIONAL_VARS\n  for var in CONFIGVARS:\n    empty_value = False\n    if not hasattr(_config, var):\n      if var in OPTIONAL_VARS:\n        log.debug(\n            'Setting non-existent but optional config variable {0:s} to '\n            'None'.format(var))\n        empty_value = True\n      else:\n        raise TurbiniaException(\n            'Required config attribute {0:s}:{1:s} not in config'.format(\n                _config.configSource, var))\n    if var in REQUIRED_VARS and getattr(_config, var) is None:\n      raise TurbiniaException(\n          'Config attribute {0:s}:{1:s} is not set'.format(\n              _config.configSource, var))\n\n    # Set the attribute in the current module\n    if empty_value:\n      setattr(sys.modules[__name__], var, None)\n    else:\n      setattr(sys.modules[__name__], var, getattr(_config, var))\n\n\ndef ParseDependencies():\n  \"\"\"Parses the config file DEPENDENCIES variable.\n\n  Raises:\n    TurbiniaException: If bad config file.\n\n  Returns:\n   dependencies(dict): The parsed dependency values.\n  \"\"\"\n  dependencies = {}\n  try:\n    for values in CONFIG.DEPENDENCIES:\n      job = values['job'].lower()\n      dependencies[job] = {}\n      dependencies[job]['programs'] = values['programs']\n      dependencies[job]['docker_image'] = values.get('docker_image')\n      dependencies[job]['timeout'] = values.get('timeout')\n  except (KeyError, TypeError) as exception:\n    raise TurbiniaException(\n        'An issue has occurred while parsing the '\n        'dependency config: {0!s}'.format(exception))\n  return dependencies\n", "path": "turbinia/config/__init__.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2016 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Basic Turbinia config.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport importlib.util\nimport importlib.machinery\nimport itertools\nimport logging\nimport os\nimport sys\nfrom turbinia import TurbiniaException\n\nDATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'\n\n# Look for config files with these names\nCONFIGFILES = ['.turbiniarc', 'turbinia.conf', 'turbinia_config_tmpl.py']\n# Look in homedir first, then /etc/turbinia\nCONFIGPATH = [\n    os.path.expanduser('~'),\n    '/etc/turbinia',\n    os.path.dirname(os.path.abspath(__file__)),\n]\n# Config setup reminder for cleaner error handling on empty configs.\nCONFIG_MSG = (\n    'Copy turbinia/config/turbinia_config_tmpl.py to ~/.turbiniarc '\n    'or /etc/turbinia/turbinia.conf, edit, and re-run.')\n\n# Required config vars\nREQUIRED_VARS = [\n    # Turbinia Config\n    'INSTANCE_ID',\n    'STATE_MANAGER',\n    'TASK_MANAGER',\n    'LOG_DIR',\n    'LOCK_FILE',\n    'TMP_RESOURCE_DIR',\n    'RESOURCE_FILE',\n    'RESOURCE_FILE_LOCK',\n    'SCALEDOWN_WORKER_FILE',\n    'OUTPUT_DIR',\n    'TMP_DIR',\n    'SLEEP_TIME',\n    'SINGLE_RUN',\n    'MOUNT_DIR_PREFIX',\n    'SHARED_FILESYSTEM',\n    'DEBUG_TASKS',\n    'DEPENDENCIES',\n    'DOCKER_ENABLED',\n    'DISABLED_JOBS',\n]\n\n# Optional config vars.  Some may be mandatory depending on the configuration\n# (e.g. if TASK_MANAGER is set to 'PSQ', then the GCE Config variables are\n# required), but these requirements are not enforced.\nOPTIONAL_VARS = [\n    # GCE CONFIG\n    'TURBINIA_PROJECT',\n    'TURBINIA_ZONE',\n    'TURBINIA_REGION',\n    'BUCKET_NAME',\n    'PSQ_TOPIC',\n    'PUBSUB_TOPIC',\n    'GCS_OUTPUT_PATH',\n    'RECIPE_FILE_DIR',\n    'STACKDRIVER_LOGGING',\n    'STACKDRIVER_TRACEBACK',\n    # REDIS CONFIG\n    'REDIS_HOST',\n    'REDIS_PORT',\n    'REDIS_DB',\n    # Celery config\n    'CELERY_BROKER',\n    'CELERY_BACKEND',\n    'KOMBU_BROKER',\n    'KOMBU_CHANNEL',\n    'KOMBU_DURABLE',\n    # Email config\n    'EMAIL_NOTIFICATIONS',\n    'EMAIL_HOST_ADDRESS',\n    'EMAIL_PORT',\n    'EMAIL_ADDRESS',\n    'EMAIL_PASSWORD',\n    # Prometheus config\n    'PROMETHEUS_ENABLED',\n    'PROMETHEUS_ADDR',\n    'PROMETHEUS_PORT',\n    # dfDewey config\n    'DFDEWEY_PG_HOST',\n    'DFDEWEY_PG_PORT',\n    'DFDEWEY_PG_DB_NAME',\n    'DFDEWEY_OS_HOST',\n    'DFDEWEY_OS_PORT',\n    'DFDEWEY_OS_URL',\n    # General config\n    'TURBINIA_COMMAND'\n]\n\n# Environment variable to look for path data in\nENVCONFIGVAR = 'TURBINIA_CONFIG_PATH'\n\nCONFIG = None\n\nlog = logging.getLogger('turbinia')\n\n\ndef LoadConfig(config_file=None):\n  \"\"\"Finds Turbinia config file and loads it.\n\n  Args:\n    config_file(str): full path to config file\n  \"\"\"\n  # TODO(aarontp): Find way to not require global var here.  Maybe a singleton\n  # pattern on the config class.\n  # pylint: disable=global-statement\n  global CONFIG\n  if CONFIG and not config_file:\n    log.debug(\n        'Returning cached config from {0:s} instead of reloading config'.format(\n            CONFIG.configSource))\n    return CONFIG\n\n  if not config_file:\n    log.debug('No config specified. Looking in default locations for config.')\n    # If the environment variable is set, take precedence over the pre-defined\n    # CONFIGPATHs.\n    configpath = CONFIGPATH\n    if ENVCONFIGVAR in os.environ:\n      configpath = os.environ[ENVCONFIGVAR].split(':')\n\n    # Load first file found\n    for _dir, _file in itertools.product(configpath, CONFIGFILES):\n      if os.path.exists(os.path.join(_dir, _file)):\n        config_file = os.path.join(_dir, _file)\n        break\n\n  if config_file is None:\n    raise TurbiniaException('No config files found')\n\n  log.debug('Loading config from {0:s}'.format(config_file))\n  # Warn about using fallback source config, but it's currently necessary for\n  # tests. See issue #446.\n  if 'turbinia_config_tmpl' in config_file:\n    log.warning('Using fallback source config. {0:s}'.format(CONFIG_MSG))\n  try:\n    config_loader = importlib.machinery.SourceFileLoader('config', config_file)\n    config_spec = importlib.util.spec_from_loader(\n        config_loader.name, config_loader)\n    _config = importlib.util.module_from_spec(config_spec)\n    config_loader.exec_module(_config)\n  except IOError as exception:\n    message = (\n        'Could not load config file {0:s}: {1!s}'.format(\n            config_file, exception))\n    log.error(message)\n    raise TurbiniaException(message)\n\n  _config.configSource = config_file\n  ValidateAndSetConfig(_config)\n\n  # Set the environment var for this so that we don't see the \"No project ID\n  # could be determined.\" warning later.\n  if hasattr(_config, 'TURBINIA_PROJECT') and _config.TURBINIA_PROJECT:\n    os.environ['GOOGLE_CLOUD_PROJECT'] = _config.TURBINIA_PROJECT\n\n  CONFIG = _config\n  log.debug(\n      'Returning parsed config loaded from {0:s}'.format(CONFIG.configSource))\n  return _config\n\n\ndef ValidateAndSetConfig(_config):\n  \"\"\"Makes sure that the config has the vars loaded and set in the module.\"\"\"\n  # Explicitly set the config path\n  setattr(sys.modules[__name__], 'configSource', _config.configSource)\n\n  CONFIGVARS = REQUIRED_VARS + OPTIONAL_VARS\n  for var in CONFIGVARS:\n    empty_value = False\n    if not hasattr(_config, var):\n      if var in OPTIONAL_VARS:\n        log.debug(\n            'Setting non-existent but optional config variable {0:s} to '\n            'None'.format(var))\n        empty_value = True\n      else:\n        raise TurbiniaException(\n            'Required config attribute {0:s}:{1:s} not in config'.format(\n                _config.configSource, var))\n    if var in REQUIRED_VARS and getattr(_config, var) is None:\n      raise TurbiniaException(\n          'Config attribute {0:s}:{1:s} is not set'.format(\n              _config.configSource, var))\n\n    # Set the attribute in the current module\n    if empty_value:\n      setattr(sys.modules[__name__], var, None)\n    else:\n      setattr(sys.modules[__name__], var, getattr(_config, var))\n\n\ndef ParseDependencies():\n  \"\"\"Parses the config file DEPENDENCIES variable.\n\n  Raises:\n    TurbiniaException: If bad config file.\n\n  Returns:\n   dependencies(dict): The parsed dependency values.\n  \"\"\"\n  dependencies = {}\n  try:\n    for values in CONFIG.DEPENDENCIES:\n      job = values['job'].lower()\n      dependencies[job] = {}\n      dependencies[job]['programs'] = values['programs']\n      dependencies[job]['docker_image'] = values.get('docker_image')\n      dependencies[job]['timeout'] = values.get('timeout')\n  except (KeyError, TypeError) as exception:\n    raise TurbiniaException(\n        'An issue has occurred while parsing the '\n        'dependency config: {0!s}'.format(exception))\n  return dependencies\n", "path": "turbinia/config/__init__.py"}]}