3737 -o outfile specify output file (default: write to stdout)
3838 -g filter_group filter users by group name (eg, 'ap1-login')
3939 -m localmaps specify a comma-delimited list of local HTCondor mapfiles to merge into outfile
40+ -n min_users Specify minimum number of users required to update the output file (default: 100)
4041 -h display this help text
4142
4243PASS for USER is taken from the first of:
@@ -64,6 +65,7 @@ class Options:
6465 ldap_user = LDAP_USER
6566 ldap_authtok = None
6667 filtergrp = None
68+ min_users = 100 # Bail out before updating the file if we have fewer than this many users
6769 localmaps = []
6870
6971
@@ -76,41 +78,12 @@ def get_osg_co_groups__map():
7678 #print("get_osg_co_groups__map()")
7779 resp_data = utils .get_osg_co_groups (options .osg_co_id , options .endpoint , options .authstr )
7880 data = utils .get_datalist (resp_data , "CoGroups" )
79- return { g ["Id" ]: g ["Name" ] for g in data }
80-
81-
82- def co_group_is_project (gid ):
83- #print(f"co_group_is_ospool({gid})")
84- resp_data = utils .get_co_group_identifiers (gid , options .endpoint , options .authstr )
85- data = utils .get_datalist (resp_data , "Identifiers" )
86- return any ( i ["Type" ] == "ospoolproject" for i in data )
87-
88-
89- def get_co_group_osggid (gid ):
90- resp_data = utils .get_co_group_identifiers (gid , options .endpoint , options .authstr )
91- data = utils .get_datalist (resp_data , "Identifiers" )
92- return list (filter (lambda x : x ["Type" ] == "osggid" , data ))[0 ]["Identifier" ]
93-
94-
95- def get_co_group_members__pids (gid ):
96- #print(f"get_co_group_members__pids({gid})")
97- resp_data = utils .get_co_group_members (gid , options .endpoint , options .authstr )
98- data = utils .get_datalist (resp_data , "CoGroupMembers" )
99- # For INF-1060: Temporary Fix until "The Great Project Provisioning" is finished
100- return [ m ["Person" ]["Id" ] for m in data if m ["Member" ] == True ]
101-
102-
103- def get_co_person_osguser (pid ):
104- #print(f"get_co_person_osguser({pid})")
105- resp_data = utils .get_co_person_identifiers (pid , options .endpoint , options .authstr )
106- data = utils .get_datalist (resp_data , "Identifiers" )
107- typemap = { i ["Type" ]: i ["Identifier" ] for i in data }
108- return typemap .get ("osguser" )
81+ return { g ["Name" ]: g ["Id" ] for g in data }
10982
11083
11184def parse_options (args ):
11285 try :
113- ops , args = getopt .getopt (args , 'u:c:s:l:a:d:f:g:e:o:h' )
86+ ops , args = getopt .getopt (args , 'u:c:s:l:a:d:f:g:e:o:h:n:m ' )
11487 except getopt .GetoptError :
11588 usage ()
11689
@@ -133,7 +106,8 @@ def parse_options(args):
133106 if op == '-e' : options .endpoint = arg
134107 if op == '-o' : options .outfile = arg
135108 if op == '-g' : options .filtergrp = arg
136- if op == '-m' : options .localmaps = arg .split ("," )
109+ if op == '-m' : options .localmaps = arg .split ("," )
110+ if op == '-n' : options .min_users = int (arg )
137111
138112 try :
139113 user , passwd = utils .getpw (options .user , passfd , passfile )
@@ -170,46 +144,15 @@ def create_user_to_projects_map(project_to_user_map, active_users, osggids_to_na
170144 return users_to_projects_map
171145
172146
173- def get_groups_data_from_api ():
174- groups = get_osg_co_groups__map ()
175- project_osggids_to_name = dict ()
176- for id ,name in groups .items ():
177- if co_group_is_project (id ):
178- project_osggids_to_name [get_co_group_osggid (id )] = name
179- return project_osggids_to_name
180-
181-
182- def get_co_api_data ():
183- try :
184- r = open (CACHE_FILENAME , "r" )
185- lines = r .readlines ()
186- if float (lines [0 ]) >= (time .time () - (60 * 60 * CACHE_LIFETIME_HOURS )):
187- entries = lines [1 :len (lines )]
188- project_osggids_to_name = dict ()
189- for entry in entries :
190- osggid_name_pair = entry .split (":" )
191- if len (osggid_name_pair ) == 2 :
192- project_osggids_to_name [int (osggid_name_pair [0 ])] = osggid_name_pair [1 ].strip ()
193- r .close ()
194- else :
195- r .close ()
196- raise OSError
197- except OSError :
198- with open (CACHE_FILENAME , "w" ) as w :
199- project_osggids_to_name = get_groups_data_from_api ()
200- print (time .time (), file = w )
201- for osggid , name in project_osggids_to_name .items ():
202- print (f"{ osggid } :{ name } " , file = w )
203-
204- return project_osggids_to_name
205-
206-
207147def get_osguser_groups (filter_group_name = None ):
208148 ldap_users = utils .get_ldap_active_users_and_groups (options .ldap_server , options .ldap_user , options .ldap_authtok , filter_group_name )
209149 topology_projects = requests .get (f"{ TOPOLOGY_ENDPOINT } /miscproject/json" ).json ()
210150 project_names = topology_projects .keys ()
151+
152+ # Get COManage group IDs to preserve ordering from pre-LDAP migration script behavior
153+ groups_ids = get_osg_co_groups__map ()
211154 return {
212- user : [g for g in groups if g in project_names ]
155+ user : sorted ( [g for g in groups if g in project_names ], key = lambda g : groups_ids . get ( g , 0 ))
213156 for user , groups in ldap_users .items ()
214157 if any (g in project_names for g in groups )
215158 and any (':members:active' in g for g in groups )
@@ -265,6 +208,9 @@ def main(args):
265208 maps .append (parse_localmap (localmap ))
266209 osguser_groups_merged = merge_maps (maps )
267210
211+ # Sanity check, confirm we have generated a "sane" amount of user -> group mappings
212+ if len (osguser_groups_merged ) < options .min_users :
213+ raise RuntimeError (f"Refusing to update output file: only { len (osguser_groups_merged )} users found" )
268214 print_usermap (osguser_groups_merged )
269215
270216
0 commit comments