@@ -87,6 +87,7 @@ import re
8787import subprocess
8888import sys
8989import unicodedata
90+ from collections import abc
9091
9192import DNS
9293
@@ -137,7 +138,8 @@ class BindTool:
137138 if (self .args .debug ):
138139 sys .excepthook = debug_hook
139140
140- self .config , self .config_file_path = self ._load_config (self .args .config_path , ('.' , os .path .join ('/etc' , self .script_name ), script_dir ))
141+ zone_name = os .path .basename (self .args .zone_file_path )
142+ self .config , self .config_dir = self ._load_config (self .args .config_path , ('.' , os .path .join ('/etc' , self .script_name ), script_dir ), zone_name )
141143 self ._config_defaults = {
142144 'defaults' : {
143145 'soa' : {
@@ -261,17 +263,43 @@ class BindTool:
261263 self .certificates = {}
262264 self .public_keys = {}
263265
264- def _load_config (self , file_path , search_paths = []):
266+ def _zone_config_file_path (self , config_file_path , zone_name ):
267+ config_dir , config_filename = os .path .split (config_file_path )
268+ if ('.' in config_filename ):
269+ name , extension = config_filename .rsplit ('.' , 1 )
270+ return os .path .join (config_dir , f'{ name } .{ zone_name } .{ extension } ' )
271+ return os .path .join (config_dir , f'{ name } .{ zone_name } ' )
272+
273+ def _merge_config (self , base , extra ):
274+ if (base is None ):
275+ base = collections .OrderedDict ()
276+ for name , value in extra .items ():
277+ if (isinstance (value , abc .Mapping )):
278+ base [name ] = self ._merge_config (base .get (name ), value )
279+ else :
280+ base [name ] = value
281+ return base
282+
283+ def _load_config_file (self , config_file_path ):
284+ if (os .path .isfile (config_file_path )):
285+ try :
286+ with open (config_file_path ) as config_file :
287+ return json .load (config_file , object_pairs_hook = collections .OrderedDict )
288+ except Exception as error :
289+ self ._error ('Error reading config file ' , config_file_path , ': ' , error , '\n ' )
290+ return {}
291+
292+ def _load_config (self , file_path , search_paths , zone_name ):
265293 search_paths = ['' ] if (os .path .isabs (file_path )) else search_paths
266- for search_path in search_paths :
294+ for search_path in reversed ( search_paths ) :
267295 config_file_path = os .path .join (search_path , file_path )
268- if ( os . path . isfile (config_file_path )):
269- try :
270- with open ( config_file_path ) as config_file :
271- return ( json . load ( config_file , object_pairs_hook = collections . OrderedDict ), os . path . abspath (config_file_path ))
272- except Exception as error :
273- self . _error ( 'Error reading config file ' , config_file_path , ': ' , error , ' \n ' )
274- return (collections . OrderedDict () , '' )
296+ zone_config_file_path = self . _zone_config_file_path (config_file_path , zone_name )
297+ if ( os . path . isfile ( config_file_path ) or os . path . isfile ( zone_config_file_path )) :
298+ config = None
299+ config = self . _merge_config ( config , self . _load_config_file (config_file_path ))
300+ config = self . _merge_config ( config , self . _load_config_file ( zone_config_file_path ))
301+ return ( config , os . path . dirname ( os . path . abspath ( config_file_path )) )
302+ return (config , '' )
275303
276304 def _message (self , * args ):
277305 message = ''
@@ -306,7 +334,7 @@ class BindTool:
306334
307335 def _directory (self , file_type ):
308336 directory = self ._config ('directories' , file_type , '' )
309- return os .path .normpath (os .path .join (os . path . dirname ( self .config_file_path ) , directory )) if (directory ) else directory
337+ return os .path .normpath (os .path .join (self .config_dir , directory )) if (directory ) else directory
310338
311339 def _key_type_suffix (self , key_type ):
312340 return self ._config ('key_type_suffixes' , key_type , '' )
0 commit comments