1
+ import json
1
2
from copy import deepcopy
2
3
import collections .abc
3
4
from diraccfg import CFG
@@ -22,7 +23,7 @@ def merge_json(d, u):
22
23
return d
23
24
24
25
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 ):
26
27
"""
27
28
Recursively merge the Operation sections
28
29
: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
46
47
merge_json (merge_root , root_section [default_setup ])
47
48
elif section in known_vos :
48
49
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 )
50
51
else :
51
52
print (f"{ section } is unknown, not touching it (other Setup, custom entry...)" )
52
53
53
54
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 ):
55
56
"""Do the merge of the Operation sections using the CFG object directly
56
57
:param cs_cfg: root of the CS
57
58
"""
@@ -93,6 +94,40 @@ def merge_cs_sections_cfg(cs_cfg: CFG, default_setup, known_vos):
93
94
cs_cfg .createNewSection ("/Operations" , comment = "Merging" , contents = operation_section )
94
95
95
96
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
+
96
131
def compare_dicts (d1 , d2 ):
97
132
"""Produces an HTML output of the diff between 2 dicts"""
98
133
return difflib .HtmlDiff ().make_file (
@@ -101,21 +136,28 @@ def compare_dicts(d1, d2):
101
136
)
102
137
103
138
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 ):
105
140
"""
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.
107
143
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
109
145
110
146
If --setup is specified, use it instead of the default one
111
147
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
113
149
"""
114
- initialize ()
115
- from DIRAC .ConfigurationSystem .Client .ConfigurationClient import ConfigurationClient
116
- from DIRAC .ConfigurationSystem .Client .ConfigurationData import gConfigurationData
117
150
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 ()
119
161
120
162
original_cs_json = cs_cfg .getAsDict ()
121
163
@@ -128,21 +170,23 @@ def main(diff_file: Path = "/tmp/diff.html", setup: str = "", execute_update: bo
128
170
master_cs = cs_json ["DIRAC" ]["Configuration" ]["MasterServer" ]
129
171
typer .echo (f"MasterCS { master_cs } " )
130
172
173
+ ######### Update the Operation section
174
+
131
175
# 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" )
133
177
first_pass_cs_json = deepcopy (cs_json )
134
178
# 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" )
136
180
# Make sure the output of the first and second pass are the same
137
181
assert first_pass_cs_json == cs_json
138
182
139
183
##############
140
184
141
185
# Redo the exercise with the CFG object
142
186
143
- merge_cs_sections_cfg (cs_cfg , default_setup , known_vos )
187
+ merge_cs_sections_operations_cfg (cs_cfg , default_setup , known_vos )
144
188
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 )
146
190
assert first_pass_cs_cfg .getAsDict () == cs_cfg .getAsDict ()
147
191
148
192
##############
@@ -153,13 +197,47 @@ def main(diff_file: Path = "/tmp/diff.html", setup: str = "", execute_update: bo
153
197
154
198
##############
155
199
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
+
156
228
# Produces diff output
157
229
158
230
# 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 :
160
232
f .write (compare_dicts (original_cs_json ["Operations" ], cs_json ["Operations" ]))
161
233
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 )
163
241
164
242
if execute_update :
165
243
compressed_data = zlib .compress (str (cs_cfg ).encode (), 9 )
0 commit comments