1+ import json
12from copy import deepcopy
23import collections .abc
34from diraccfg import CFG
@@ -22,7 +23,7 @@ def merge_json(d, u):
2223 return d
2324
2425
25- def merge_cs_sections_json (root_section , default_setup , known_vos , name = None , merge_in = None ):
26+ def merge_cs_sections_operations_json (root_section , default_setup , known_vos , name = None , merge_in = None ):
2627 """
2728 Recursively merge the Operation sections
2829 :param root_section: start of the section we are looking at
@@ -46,12 +47,12 @@ def merge_cs_sections_json(root_section, default_setup, known_vos, name=None, me
4647 merge_json (merge_root , root_section [default_setup ])
4748 elif section in known_vos :
4849 print (f"{ section } is a vo." )
49- merge_cs_sections_json (root_section [section ], default_setup , known_vos , name = section )
50+ merge_cs_sections_operations_json (root_section [section ], default_setup , known_vos , name = section )
5051 else :
5152 print (f"{ section } is unknown, not touching it (other Setup, custom entry...)" )
5253
5354
54- def merge_cs_sections_cfg (cs_cfg : CFG , default_setup , known_vos ):
55+ def merge_cs_sections_operations_cfg (cs_cfg : CFG , default_setup , known_vos ):
5556 """Do the merge of the Operation sections using the CFG object directly
5657 :param cs_cfg: root of the CS
5758 """
@@ -93,6 +94,40 @@ def merge_cs_sections_cfg(cs_cfg: CFG, default_setup, known_vos):
9394 cs_cfg .createNewSection ("/Operations" , comment = "Merging" , contents = operation_section )
9495
9596
97+ def merge_cs_sections_systems_json (cs_json , default_setup : str ):
98+ """
99+ Recursively merge the Systems sections
100+ :param root_section: start of the section we are looking at
101+ :param name: The name of the section, just used for printing
102+ :param merge_in: name of the section to merge in (if set, do not merge in the root). Only used for Defaults
103+ """
104+ for system in list (cs_json ["Systems" ]):
105+ instance = cs_json ["DIRAC" ]["Setups" ][default_setup ][system ]
106+
107+ # print(f"Merging {default_setup} to {merge_in}")
108+ merge_json (cs_json ["Systems" ][system ], cs_json ["Systems" ][system ][instance ])
109+
110+
111+ def merge_cs_sections_systems_cfg (cs_cfg : CFG , default_setup : str ):
112+ """Do the merge of the System sections using the CFG object directly
113+ :param cs_cfg: root of the CS
114+ """
115+ all_systems_section = cs_cfg .getAsCFG ("/Systems" )
116+ for system in list (all_systems_section .getAsDict ()):
117+ instance = cs_cfg ["DIRAC" ]["Setups" ][default_setup ][system ]
118+
119+ merged_section = all_systems_section [system ].mergeWith (all_systems_section [system ][instance ])
120+ all_systems_section .deleteKey (system )
121+ all_systems_section .createNewSection (
122+ system ,
123+ comment = "Automatic merging to remove Setups" ,
124+ contents = merged_section ,
125+ )
126+
127+ cs_cfg .deleteKey ("/Systems" )
128+ cs_cfg .createNewSection ("/Systems" , comment = "Merging" , contents = all_systems_section )
129+
130+
96131def compare_dicts (d1 , d2 ):
97132 """Produces an HTML output of the diff between 2 dicts"""
98133 return difflib .HtmlDiff ().make_file (
@@ -101,21 +136,28 @@ def compare_dicts(d1, d2):
101136 )
102137
103138
104- def main (diff_file : Path = "/tmp/diff.html " , setup : str = "" , execute_update : bool = False ):
139+ def main (diff_folder : Path = "/tmp/" , master_cs_file : Path = " " , setup : str = "" , execute_update : bool = False ):
105140 """
106- Remove the Setup sections from the Operations section.
141+ Copy the Setup sections from the Operations section into the Default part.
142+ Copy the Instance sections of the Systems in the System directly.
107143
108- If --diff-file is specified, dump the html comparison at this location
144+ If --diff-folder is specified, dump the html comparison at this location
109145
110146 If --setup is specified, use it instead of the default one
111147
112- If --execute-update is set, it will attempt to actually update the CS
148+ If --execute-update is set, it will attempt to actually update the CS. This does not work if master_cs_file is specified
113149 """
114- initialize ()
115- from DIRAC .ConfigurationSystem .Client .ConfigurationClient import ConfigurationClient
116- from DIRAC .ConfigurationSystem .Client .ConfigurationData import gConfigurationData
117150
118- cs_cfg = gConfigurationData .getRemoteCFG ()
151+ if master_cs_file .is_file ():
152+ if execute_update :
153+ raise NotImplementedError ("Cannot update the Master CS if starting from a config file !" )
154+ cs_cfg = CFG ().loadFromFile (master_cs_file )
155+ else :
156+ initialize ()
157+ from DIRAC .ConfigurationSystem .Client .ConfigurationClient import ConfigurationClient
158+ from DIRAC .ConfigurationSystem .Client .ConfigurationData import gConfigurationData
159+
160+ cs_cfg = gConfigurationData .getRemoteCFG ()
119161
120162 original_cs_json = cs_cfg .getAsDict ()
121163
@@ -128,21 +170,23 @@ def main(diff_file: Path = "/tmp/diff.html", setup: str = "", execute_update: bo
128170 master_cs = cs_json ["DIRAC" ]["Configuration" ]["MasterServer" ]
129171 typer .echo (f"MasterCS { master_cs } " )
130172
173+ ######### Update the Operation section
174+
131175 # First do a merge using JSON
132- merge_cs_sections_json (cs_json ["Operations" ], default_setup , known_vos , "Operations" , "Defaults" )
176+ merge_cs_sections_operations_json (cs_json ["Operations" ], default_setup , known_vos , "Operations" , "Defaults" )
133177 first_pass_cs_json = deepcopy (cs_json )
134178 # Do it twice, because runing over it twice shouldn't change the result
135- merge_cs_sections_json (cs_json ["Operations" ], default_setup , known_vos , "Operations" , "Defaults" )
179+ merge_cs_sections_operations_json (cs_json ["Operations" ], default_setup , known_vos , "Operations" , "Defaults" )
136180 # Make sure the output of the first and second pass are the same
137181 assert first_pass_cs_json == cs_json
138182
139183 ##############
140184
141185 # Redo the exercise with the CFG object
142186
143- merge_cs_sections_cfg (cs_cfg , default_setup , known_vos )
187+ merge_cs_sections_operations_cfg (cs_cfg , default_setup , known_vos )
144188 first_pass_cs_cfg = cs_cfg .clone ()
145- merge_cs_sections_cfg (cs_cfg , default_setup , known_vos )
189+ merge_cs_sections_operations_cfg (cs_cfg , default_setup , known_vos )
146190 assert first_pass_cs_cfg .getAsDict () == cs_cfg .getAsDict ()
147191
148192 ##############
@@ -153,13 +197,47 @@ def main(diff_file: Path = "/tmp/diff.html", setup: str = "", execute_update: bo
153197
154198 ##############
155199
200+ ######### END Update the Operation section
201+
202+ ######### Update the System section
203+
204+ # First do a merge using JSON
205+ merge_cs_sections_systems_json (cs_json , default_setup )
206+ first_pass_cs_json = deepcopy (cs_json )
207+ # Do it twice, because runing over it twice shouldn't change the result
208+ merge_cs_sections_systems_json (cs_json , default_setup )
209+ # Make sure the output of the first and second pass are the same
210+ assert first_pass_cs_json == cs_json
211+
212+ # Redo the exercise with the CFG object
213+ merge_cs_sections_systems_cfg (cs_cfg , default_setup )
214+ first_pass_cs_cfg = cs_cfg .clone ()
215+ merge_cs_sections_systems_cfg (cs_cfg , default_setup )
216+ assert first_pass_cs_cfg .getAsDict () == cs_cfg .getAsDict ()
217+
218+ ##############
219+
220+ # Finally, make sure we get the same thing in json and CFG
221+
222+ assert cs_cfg .getAsDict () == cs_json
223+
224+ ##############
225+
226+ ######### END Update the System section
227+
156228 # Produces diff output
157229
158230 # print(compare_dicts(original_cs_json["Operations"], cs_cfg.getAsDict("/Operations")))
159- with open (diff_file , "w" ) as f :
231+ with open (diff_folder / "diff_operations.html" , "w" ) as f :
160232 f .write (compare_dicts (original_cs_json ["Operations" ], cs_json ["Operations" ]))
161233
162- typer .echo (f"Diff written in { diff_file } " )
234+ with open (diff_folder / "diff_systems.html" , "w" ) as f :
235+ f .write (compare_dicts (original_cs_json ["Systems" ], cs_json ["Systems" ]))
236+
237+ typer .echo (f"Diff written in { diff_folder } " )
238+ cs_cfg .writeToFile (diff_folder / "modifed_cs.cfg" )
239+ with open (diff_folder / "modifed_cs.json" , "w" ) as f :
240+ json .dump (cs_json , f , indent = 3 )
163241
164242 if execute_update :
165243 compressed_data = zlib .compress (str (cs_cfg ).encode (), 9 )
0 commit comments