Use deepcopy when copying ansible logging config
When using shallow copies of these data structures there is a race
between writing out the config to disk and some other Job or Server
coming along and updating handler filenames for that job/server before
the previous config is fully written to disk.
We can illustrate this in a simple example case:
>>> d = {'foo': { 'bar': 1 } }
>>> d1 = d.copy()
>>> d2 = d.copy()
>>> d1
{'foo': {'bar': 1}}
>>> d2
{'foo': {'bar': 1}}
>>> d1['foo']['bar'] = 2
>>> d1
{'foo': {'bar': 2}}
>>> d2
{'foo': {'bar': 2}}
>>>
Notice that the inner dict is updated in both d1 and d2 because the foo
key points at a reference to that inner dict and not a copy.
We can avoid this problem entirely using deepcopies.
Change-Id: I8c1ac002af76c516621396b13375913d5d60f092
diff --git a/zuul/ansible/logconfig.py b/zuul/ansible/logconfig.py
index 5425d72..7ef43a8 100644
--- a/zuul/ansible/logconfig.py
+++ b/zuul/ansible/logconfig.py
@@ -13,6 +13,7 @@
# under the License.
import abc
+import copy
import logging.config
import json
import os
@@ -169,7 +170,7 @@
def __init__(self, config=None, job_output_file=None):
if not config:
- config = _DEFAULT_JOB_LOGGING_CONFIG.copy()
+ config = copy.deepcopy(_DEFAULT_JOB_LOGGING_CONFIG)
super(JobLoggingConfig, self).__init__(config=config)
if job_output_file:
self.job_output_file = job_output_file
@@ -191,7 +192,7 @@
def __init__(self, config=None, server=None):
if not config:
- config = _DEFAULT_SERVER_LOGGING_CONFIG.copy()
+ config = copy.deepcopy(_DEFAULT_SERVER_LOGGING_CONFIG)
super(ServerLoggingConfig, self).__init__(config=config)
if server:
self.server = server
@@ -207,7 +208,7 @@
# config above because we're templating out the filename. Also, we
# only want to add the handler if we're actually going to use it.
for name, handler in _DEFAULT_SERVER_FILE_HANDLERS.items():
- server_handler = handler.copy()
+ server_handler = copy.deepcopy(handler)
server_handler['filename'] = server_handler['filename'].format(
server=server)
self._config['handlers'][name] = server_handler