powershellloopsrecursionobject-graph

PS recursive function to generate full path


from an API I get the following array of PSobjects

$testgroups

total device_groups
----- -------------
 1062 {@{id=-2ZPmENMTTSmfNxuGd2Emw; name=Server; description=; created=27/06/2024 10:07:39; modified=27/06/2024 10:07:39; parent_id=T5dNIARCR7OnuzW8IIAsWg...},

$testgroups.device_groups[0..2]

id          : -2ZPmENMTTSmfNxuGd2Emw
name        : Server
description : 
created     : 27/06/2024 10:07:39
modified    : 27/06/2024 10:07:39
parent_id   : T5dNIARCR7OnuzW8IIAsWg

id          : -6XA_2FOSZSw5Bk6HXLewQ
name        : SBC
description : 
created     : 27/06/2024 10:07:40
modified    : 27/06/2024 10:07:40
parent_id   : M8ZBfSjGQtamIAJZpVI7Cw

id          : -GaDYTJbSPaid64tWUDQ_A
name        : RT SCOM_GW
description : group for testing
created     : 27/06/2024 10:07:41
modified    : 27/06/2024 10:07:41
parent_id   : CbuM2_KDQ82BBPlS4lx_Mg

As you can see there is a parent_id property which refers to its parent group. the "root" group has the property empty. I'm wrapping my head around making a recursive function to generate the full path for each groups, but didn't manage to get anything working.

Ideally the format of the new "fullPath" property could look like this : root\subgroup1\subgroup2 for each object


Solution

  • Managed to get it working. Apologies if I wasn't clear enough the demand and explanation.

    The goal was to create a new property (fullPathName) that generates a full path for every groups, looking up every parent groups until we hit the root group. For example, we'd have 2 psobjects, one being the "parent" of the other.

    $testgroups.device_groups | Where-Object { $_.id -eq "F8S_MJ4tSPi-D_Eoofgo2w" -or $_.id -eq "Fmp5838YRsyElHM27PdZww" }}
    
    id           : F8S_MJ4tSPi-D_Eoofgo2w
    name         : subgroup 1
    description  : 
    created      : 04/07/2024 14:19:00
    modified     : 04/07/2024 14:19:00
    parent_id    : Fmp5838YRsyElHM27PdZww
    
    id           : Fmp5838YRsyElHM27PdZww
    name         : Aurelien policies tests
    description  : 
    created      : 04/07/2024 14:18:52
    modified     : 04/07/2024 14:18:52
    parent_id    : gBuOolHrTt64XdEmfRM60A
    

    Following recursive function did the trick

    function Get-NameChain {
        param (
            [PSCustomObject]$CurrentGroup,
            [Array]$AllGroups,
            [String]$Chain = ""
        )
        # If the current group is root (no parent_id), prepend its name to the chain.
        if (-not $CurrentGroup.parent_id) {
            if ($Chain -eq "") {
                return $CurrentGroup.name # If chain is empty, it's the root group.
            } else {
                return $CurrentGroup.name + "\" + $Chain # Prepend root name to chain.
            }
        } else {
            # Find the parent group.
            $ParentGroup = $AllGroups | Where-Object { $_.id -eq $CurrentGroup.parent_id }
            if ($ParentGroup) {
                # If there's a parent, prepend the parent's name to the chain and recurse.
                $NewChain = if ($Chain -eq "") { $CurrentGroup.name } else { $CurrentGroup.name + "\" + $Chain }
                return Get-NameChain -CurrentGroup $ParentGroup -AllGroups $AllGroups -Chain $NewChain
            } else {
                # If no parent found (which shouldn't happen), return the current chain.
                return $Chain
            }
        }
    }
    

    The following command looped through every group to use the recursive function

    $testgroups.device_groups | ForEach-Object {
                 $FullNameChain = Get-NameChain -CurrentGroup $_ -AllGroups $testgroups.device_groups -Chain ""
                 $_ | Add-Member -NotePropertyName "fullPathName" -NotePropertyValue $FullNameChain -Force               
             }