Skip to Content.
Sympa Menu

grouper-users - [grouper-users] RE: How to delete direct memberships without touching subgroups and their members

Subject: Grouper Users - Open Discussion List

List archive

[grouper-users] RE: How to delete direct memberships without touching subgroups and their members


Chronological Thread 
  • From: "Redman, Chad" <>
  • To: Rory Larson <>, "" <>
  • Subject: [grouper-users] RE: How to delete direct memberships without touching subgroups and their members
  • Date: Mon, 12 Feb 2018 16:24:55 +0000
  • Accept-language: en-US
  • Authentication-results: spf=none (sender IP is ) ;
  • Ironport-phdr: 9a23:OEY/Mxe/+LNWPEnxjgtwfykzlGMj4u6mDksu8pMizoh2WeGdxc26ZBWN2/xhgRfzUJnB7Loc0qyK6/mmATRIyK3CmUhKSIZLWR4BhJdetC0bK+nBN3fGKuX3ZTcxBsVIWQwt1Xi6NU9IBJS2PAWK8TW94jEIBxrwKxd+KPjrFY7OlcS30P2594HObwlSizexfa5+IA+qoQnNq8IbnZZsJqEtxxXTv3BGYf5WxWRmJVKSmxbz+MK994N9/ipTpvws6ddOXb31cKokQ7NYCi8mM30u683wqRbDVwqP6WACXWgQjxFFHhLK7BD+Xpf2ryv6qu9w0zSUMMHqUbw5Xymp4rx1QxH0ligIKz858HnWisNuiqJbvAmhrAF7z4LNfY2ZKOZycqbbcNgHR2ROQ9xRWjRBDI2icoUPE+QPM+VWr4b/plsBsRSwCga3CePz0z9EmmP60bEm3+g/FwzNwQwuH8gJsHTRtNj5OrscXv6ow6nN1zrDaeta0irj5YjIaB8uvP+AVq93fMXNyUkgDR7KgU2KqYP7IjyV0/4Cs26A4up9U+Kgl3QrpB9srTiy38ohjJTCiIENyl3c6yl22po5KcC9RUJmfNKoDZ5dty+VOodqXs8vRm9otzg1x7AJvJO2eSkHxIg8yBLHdvCKc5aE7gj9WOqLPDt0mGxpdKiiixu98kWs0uP8Wde33VpWqydIl8XDu3AM2hzd78WKSfRw/km71juK1w3c9PpLLlsxmKfUKpMu36U/m5wOukrZBCD2gl/5jKqOe0Uk5Oeo7+Pnb63+qJKAMIF4lh/yPr0zlMKnHOg0Kw8OUHOF9uim073j4FH5T65Njv0rlKnWrYrWJdwBpq6+Hw9azJos6wq+Dzeh1tQUh34HLE9ZeBKDiIjpPFLOLOrkAve4hlSgiDZrx/bYMb39GpjBMGLMnKv8cbt49kJQ1Rc/wNVR559bFr0NPPf+WkHvu9HXARI0Ngm5zuf7BNpmzo8eXHiAAq6dMKPcq1+I4ecvLvGQa48VojnyNuAq5+TwgnAknF8SZ6+p0IAKaHC+AvtqOVuWbmfxgtsZC2cFohI+TPD2iF2FSTNTaGyyX6Uh5jEjFo2mF57PRp22gLOfxie7BYZbZmRHClCXDXfobJuIV+0NaCKUPs9ujCYEVb6/RI89yx2irhH1xKd6LrmcxipNj5X5xZBR7vfIkhd6oSZwBt6G1GfUZ3xymiUFSyJgmOg1rlZ610+Oy+1lmPFCDvRS4e9ESAE3KcSawuBnQZimVRjGY8+EUhO7Wdi8GhkwSM482dkDfxw7Ftm/2EPtxS2vVvUvmrCODZpwuonc1nS7b5J2y3/K47Msg1wvRONSM2bgi6JioVuAT7XVmlmUwv75PZ8X2zTAoSLalTKD
  • Spamdiagnosticmetadata: NSPM
  • Spamdiagnosticoutput: 1:99

Just one more note, the subject source for groups is "g:gsa" (or more
formally, SubjectFinder.internal_getGSA().getId()). So you can filter
non-groups with:

!m.getSubjectSourceId().equals("g:gsa")

There is no Member.isGroup(), although there is a toGroup() method if you
already know it's a group.

-Chad


-----Original Message-----
From: Rory Larson
[mailto:]

Sent: Sunday, February 11, 2018 6:48 PM
To: Redman, Chad
<>;


Subject: RE: How to delete direct memberships without touching subgroups and
their members

Hi Chad,

Thanks very much for this! That was just what I needed to get over the hump.
The way that eventually worked for me was essentially as follows:

gsh 0% sess = GrouperSession.startRootSession();
gsh 1% sw = GroupFinder.findByName(sess, "our:campus:group:studentworker",
true);
gsh 2% immediateMembers = sw.getImmediateMembers();
gsh 3% for (Member m: sw.getMembers()) {if ((immediateMembers.contains(m))
&& (m.getSubject().getName().length() >= 1) &&
(m.getSubject().getName().substring(0,1).compareTo("Z") <= 0))
{System.out.println("Deleting " + m.getSubject().getName());
sw.deleteMember(m, false);} }

Some takeaways:

1. Trying to do mass deletes like this through the UI is slow, and crashes
regularly every 10-25 records. Doing it through gsh is relatively quick,
perhaps about two records per second, and can apparently chew through
thousands in a row without ever choking.

2. The group.deleteMember(m, false) call deletes only direct memberships, not
indirect ones. This makes perfect sense, of course. I needn't have worried
on that score.

3. At first, the evidence seemed to indicate to me that group.getMembers()
and perhaps group.getImmediateMembers() returned only subjects (direct member
people), not member groups. If that were so, it should be possible to base
the mass delete solely on the [ if (immediateMembers.contains(m)) ] part of
the query. A final experiment before trying it showed this to be wrong. The
reason the member groups were not showing up under the full conditional that
filtered for the initial part of the name, is that the "name" returned for
the member groups is their ID path. A student worker like Sally Brown would
start with uppercase "S", which is less than "Z". But the ID path for our
member groups happened to begin with a lowercase "u", which is greater. So I
was apparently right to be worried about the possibility of deleting the
member groups this whole procedure was intended to save. This twist was
unexpected.

At any rate, the superfluous direct members have been deleted now, and our
Student Worker group seems to be happy. Again, thanks so much for chiming in
and sharing your expertise!

Best,
Rory


-----Original Message-----
From: Redman, Chad
[mailto:]

Sent: Saturday, February 10, 2018 12:44 AM
To: Rory Larson
<>;


Subject: RE: How to delete direct memberships without touching subgroups and
their members

Hi Rory,

The Group class has methods for getImmediateMembers() and
getEffectiveMembers(), so the combination of those two would make it a
straightforward task. Here are two sample scripts. Depending on your GSH
version (original bsh or the newer groovy), you may need to fold the
multi-line blocks into a single line.


# (1) Print tab-separated summary of all group members, and flags for direct,
indirect, or both # Depending on the results, you could use the data to
create a scrutinized list of Ids to delete, then import it and delete in a
loop

me = SubjectFinder.findByIdentifierAndSource("my-username", "pid", true);
session = GrouperSession.start(me); // OR: session =
GrouperSession.startRootSession(True)

group = GroupFinder.findByName(session, "tmp:my:group", true);

effectiveMembers = group.getEffectiveMembers(); immediateMembers =
group.getImmediateMembers();

System.out.println(String.join("\t", "id", "name", "Effective", "Immediate"));

for (Member m: group.getMembers()) {
System.out.print(m.getSubject().getId() + "\t" + m.getSubject().getName()
+ "\t");
System.out.print(effectiveMembers.contains(m).toString() + "\t");
System.out.println(immediateMembers.contains(m).toString() + "\t"); }



# (2) Get the immediate and effective members for a specific source ("pid" in
this example), intersect them to find the redundant ones # This has a dryRun
flag, so you can test first

sources = new HashSet<Source>()
sources.add(SourceManager.getInstance().getSource("pid"))

effectiveUsers = group.getEffectiveMembers(Group.getDefaultList(), sources,
null) immediateUsers = group.getImmediateMembers(Group.getDefaultList(),
sources, null)

# use retainAll() to find the intersection; i.e., users both as effective and
immediate member
immediateUsers.retainAll(effectiveUsers)

System.out.println("There are " + immediateUsers.size() + " users having both
direct + indirect memberships");

dryRun = true

for (Member m: immediateUsers) {
if (dryRun) {
System.out.println("Ok to delete " + m.getSubject().getId());
} else {
System.out.println("Deleting " + m.getSubject().getId());
group.deleteMember(m, false);
}
}


Hope this helps!

Chad








-----Original Message-----
From:


[mailto:]
On Behalf Of Rory Larson
Sent: Friday, February 09, 2018 8:52 PM
To:

Subject: [grouper-users] How to delete direct memberships without touching
subgroups and their members

Hello,

I have a group with largely redundant membership. It was originally created
with direct memberships from one data source, and then given a few groups
from another data source that had most of the same people, in a process
intended to be a smooth transition. Now I would like to remove all the old
direct memberships from the group, leaving only the new subgroups with their
members.

When I try this through the Grouper New UI, marking all direct members on the
page for deletion, it grinds for a while, deletes a few members, and then
crashes with a pink error message telling me to start over. It works as
advertised for the few it does delete, but since I'm dealing with a
membership of over 7500, this route does not look promising.

I would like to handle this through gsh, but I'm having trouble figuring out
how to filter. The query I've been developing might look something like this:

$ for (mem : getMembers("my:group:name")) {System.out.println("deleting: " +
mem.getName()); mem.delete();}

But I'm queasy about using this, because I'm not sure what all I'm deleting,
and where. I don't want to delete my subgroups, and I don't want to delete
anybody inside those subgroups. I tried testing with an if statement to
check names against who shows up with direct and indirect memberships in the
New UI, and was disappointed to discover that getMembers() returns both
direct and indirect members.

Is there a method that will return only the direct members of a group, but
not member groups? Or is there a filter I could use to select only the ones
I want through an if statement?

Thanks,
Rory




Archive powered by MHonArc 2.6.19.

Top of Page