#!/usr/bin/perl # # This script is to be used for pulling projects, and unique IDs, based on projects and team areas from a CLM web application # Currently this script can be used to pull data from CCM, and QM # # Usage: # ./clmProjectUsersPull.pl [admins|users|both] # # Leaving the lasta argument blank will just print out project areas use LWP::UserAgent; use XML::Simple; ################ #= Start Main =# ################ # Take in the arguments my ($jazzURI, $jazzUser, $jazzPass, $select) = @ARGV; # Verify selection if ($select) { unless ( ($select eq 'admins') or ($select eq 'members') or ($select eq 'both') ) { print "Bad selection value $select, choose admins,members,both or leave blank\n"; exit(1); } } # Create the global browser agent and other variables my $browser = LWP::UserAgent->new; my $projectArea; my %teamAreas, %uniqueUsers; # Verify credentials lwpAuth(); # Gather project areas my %projects = getProjectAreas(); # If a selection was chosen, continue to gather user information, else just print the projects if ($select) { if (defined $projects->{'name'}) { # Single project area $projectArea = $projects->{'name'}; if ($projects->{'archived'} eq "false") { %teamAreas = getProjectTeamAreas($projectArea, $projects->{'itemId'}); gatherUserData($projectArea,%teamAreas); printUserData($projectArea); } } else { # Multiple project areas foreach $projectArea (keys %projects ) { if ($projects{$projectArea}{'archived'} eq "false") { %teamAreas = getProjectTeamAreas($projectArea, $projects{$projectArea}{'itemId'}); gatherUserData($projectArea,%teamAreas); printUserData($projectArea); } } } } else { # Just print projects if (defined $projects->{'name'}) { # Single project area if ($projects->{'archived'} eq "false") { print $projects->{'name'} . "\n"; } } else { # Multiple project areas foreach $projectArea (sort {lc($a) cmp lc($b)} keys %projects) { if ( $projects{$projectArea}{'archived'} eq "false" ) { print "$projectArea\n"; } } } } ############## #= End Main =# ############## # Verify credentials before progressing sub lwpAuth { $browser->cookie_jar({ $jazzURI . "cookie.txt"}); push @{ $browser->requests_redirectable }, 'POST'; $response = $browser->get( $jazzURI . "/secure/service/com.ibm.team.repository.service.internal.webuiInitializer.IWebUIInitializerRestService/initializationData"); $response = $browser->post( $jazzURI . "/j_security_check", [ j_username => $jazzUser, j_password => $jazzPass ], ); die "$url error: ", $response->status_line unless $response->is_success; } # Generate a hash of projects sub getProjectAreas { my $URI = $jazzURI . "/service/com.ibm.team.process.internal.common.service.IProcessRestService/allProjectAreas"; my $response = $browser->get($URI); my $xmlResp = XMLin($response->content); my $projects = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'values'}; if (! $projects) { print "No Project Areas\n"; exit(1); } return(%$projects); } # Generate a hash of team areas sub getProjectTeamAreas { my ($projectArea, $projectAreaUUID) = @_; # This service will get you the team areas itemId's my $URI = $jazzURI . "/service/com.ibm.team.process.internal.service.web.IProcessWebUIService/projectHierarchy?uuid=" . $projectAreaUUID; my $response = $browser->get($URI); my $xmlResp = XMLin($response->content); my %teamAreas = (); if ( defined $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'name'} ) { # single project $repoProj = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'name'}; $teamAreas{$repoProj}{'itemId'} = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'itemId'}; if ( defined $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'children'}) { # subteams %teamAreas = getTeamAreas($repoProj,$xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'children'},\%teamAreas); } # else no subteams } else { # multiple projects foreach $repoProj ( keys %{$xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}} ) { next if ( $repoProj eq '' ); $teamAreas{$repoProj}{'itemId'} = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{$repoProj}{'itemId'}; %teamAreas = getTeamAreas($repoProj,$xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{$repoProj}{'children'},\%teamAreas); } # end foreach $repoProj } # end if its a single project return (%teamAreas) } # getProjectTeamMembers # Recursive getTeams sub getTeamAreas { my $repoProj = shift; my $child = shift; my (%teamAreas) = %{$_[0]}; my $team = "" ; my $teamid = ""; my @teams = () ; # A lone subteam if ( defined $child->{'name'} ) { $team = $child->{'name'}; $teamid = $child->{'itemId'}; # print "\t\t$team\n"; $teamAreas{$repoProj}{'teams'}{$team}{'itemId'} = $teamid; if ( defined $child->{'children'} ) { %teamAreas = getTeamAreas( $repoProj, $child->{'children'},\%teamAreas); } # end if defined $child{'children'} } # end lone subteam else { # a multi subteam if ( ref $child eq 'HASH' ) { @teams = ( keys %{$child} ); foreach $team ( @teams ) { $teamAreas{$repoProj}{'teams'}{$team}{'itemId'} = $child->{$team}{'itemId'}; if ( defined ${child}->{$team}{'children'} ) { %teamAreas = getTeamAreas($repoProj,$child->{$team}{'children'},\%teamAreas); } # end if defined ${child}{$team}{'children'} } # end foreach $team } else { print "WARNING: Unknown Jazz Project Structure in project: $repoProj\n"; } # end if ref $child eq HASH } # end multi child scenario return(%teamAreas); } # Helper subroutine to gather user data based on the projects team area hierarchy sub gatherUserData { my ($projectArea, %teamAreas) = @_; my $teamArea, $userKey; # Main project area, should always be defined if we made it this far if (defined $teamAreas{$projectArea}{'itemId'}) { getProjectTeamUsers($projectArea, $teamAreas{$projectArea}{'itemId'}); # Parse through the team areas, and sub-team areas $subTeamAreas = $teamAreas{$projectArea}{'teams'}; foreach $teamArea (keys %{$subTeamAreas}) { getProjectTeamUsers($projectArea, $subTeamAreas->{$teamArea}{'itemId'}); } } } # Gets the users from the project and team areas then passes the values to a helper subroutine to be set in the uniqueUser hash sub getProjectTeamUsers { my ($projectArea, $areaItemId) = @_; my $user, $URI; my %users; # Different URI's for main project area vs team area, very reasonable assumption that we wont hit a project/team area with more than 100K users if ($projects{$projectArea}{'itemId'} eq $areaItemId) { $URI = $jazzURI . "/service/com.ibm.team.process.internal.service.web.IProcessWebUIService/projectAreaByUUIDWithLimitedMembers?processAreaItemId=" . $areaItemId . "&maxMembers=100000"; } else { $URI = $jazzURI . "/service/com.ibm.team.process.internal.service.web.IProcessWebUIService/teamAreaByUUIDWithLimitedMembers?processAreaItemId=" . $areaItemId . "&maxMembers=100000"; } my $response = $browser->get($URI); my $xmlResp = XMLin($response->content); if ( ($select eq 'members') or ($select eq 'both') ) { $users = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'members'}; # This is the actual data push, one common change might be to change 'userId' to 'emailAddress' if ($users->{'name'}) { pushToUserHash($projectArea,$users->{'userId'},'member'); } else { foreach $user ( keys %$users ) { pushToUserHash($projectArea,$users->{$user}{'userId'},'member'); } } } if ( ($select eq 'admins') or ($select eq 'both') ) { $users = $xmlResp->{'soapenv:Body'}{'response'}{'returnValue'}{'value'}{'admins'}; if ($users->{'name'}) { pushToUserHash($projectArea,$users->{'userId'},'admin'); } else { foreach $user ( keys %$users ) { pushToUserHash($projectArea,$users->{$user}{'userId'},'admin'); } } } } # Helper subroutine to generate a unique user hash, defining users as members/admins sub pushToUserHash { my ($projectArea, $user, $type) = @_; unless (exists $uniqueUsers{$projectArea}{$user}{$type}) { $uniqueUsers{$projectArea}{$user}{$type} = ''; } } # Prints the user data, which is now compiled in the uniqueUser hash sub printUserData { my ($projectArea) = @_; my $userKey; # Done collecting for the project, print results foreach $userKey (sort {lc($a) cmp lc($b)} keys %{$uniqueUsers{$projectArea}}) { # Print out if they are an admin, member, or both if (exists $uniqueUsers{$projectArea}{$userKey}{'admin'}) { print "'$projectArea',$userKey,admin\n"; } if (exists $uniqueUsers{$projectArea}{$userKey}{'member'}) { print "'$projectArea',$userKey,member\n"; } } }