Providers/FreeIPA/Public/New-FreeIPANetgroup.ps1

function New-FreeIPANetgroup {
    <#
    .EXTERNALHELP TestEnvironment-Help.xml
    .SYNOPSIS
        Creates the seeded FreeIPA netgroups from Data\FreeIPANetgroups.csv, with their members
    #>


    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter()]
        [string[]]$NetgroupName,

        [Parameter()]
        [switch]$PassThru
    )

    $connection = Get-FreeIPAConnection
    $marker = Get-FreeIPASeedMarker -Connection $connection

    $csvPath = Join-Path -Path (Get-FreeIPADataPath) -ChildPath 'FreeIPANetgroups.csv'
    $rows = @(Import-Csv -Path $csvPath -Encoding UTF8)
    if ($NetgroupName) {
        $rows = @($rows | Where-Object { $NetgroupName -contains $_.Name })
        $unknown = @($NetgroupName | Where-Object { $rows.Name -notcontains $_ })
        if ($unknown) { throw "No definition in $csvPath for: $($unknown -join ', ')" }
    }

    $result = [PSCustomObject]@{
        TotalNetgroups     = $rows.Count
        CreatedNetgroups   = 0
        UpdatedNetgroups   = 0
        MembershipsApplied = 0
        Netgroups          = @()
        Errors             = @()
    }

    $existing = @{}
    foreach ($entry in (Get-FreeIPASeededObject -Type Netgroups -Connection $connection)) { $existing[[string](@($entry.cn)[0])] = $entry }

    $split = { param($value) @([string]$value -split ';' | Where-Object { $_ }) }
    $resolve = { param($keys, $kind) @(& $split $keys | ForEach-Object { Resolve-FreeIPASeedName -Key $_ -Kind $kind -Marker $marker -Connection $connection }) }

    $netgroups = [System.Collections.Generic.List[object]]::new()
    $created = @{}

    foreach ($row in $rows) {
        $name = Resolve-FreeIPASeedName -Key $row.Name -Marker $marker -Connection $connection
        if (-not $PSCmdlet.ShouldProcess($name, 'Create FreeIPA netgroup')) { continue }

        try {
            $options = @{ description = ('{0} {1}' -f $row.Description, $marker.Marker).Trim() }
            if ($row.UserCategory) { $options['usercategory'] = $row.UserCategory }
            if ($row.HostCategory) { $options['hostcategory'] = $row.HostCategory }

            if ($existing.ContainsKey($name)) {
                $null = Invoke-FreeIPARequest -Method 'netgroup_mod' -Arguments $name -Options $options -Connection $connection -IgnoreError 'EmptyModlist'
                $result.UpdatedNetgroups++
            }
            else {
                $null = Invoke-FreeIPARequest -Method 'netgroup_add' -Arguments $name -Options $options -Connection $connection
                $result.CreatedNetgroups++
                Write-Verbose "Created netgroup $name"
            }
            $created[$row.Name] = $name
            $netgroups.Add([PSCustomObject]@{ Key = $row.Name; Name = $name })
        }
        catch {
            $message = "Failed to create netgroup '$name': $($_.Exception.Message)"
            $result.Errors += $message
            Write-Error $message
        }
    }

    # Members second, once every netgroup a row could name exists.
    foreach ($row in $rows) {
        if (-not $created.ContainsKey($row.Name)) { continue }
        $name = $created[$row.Name]
        $members = @{
            user      = @(& $split $row.Users)
            group     = @(& $resolve $row.Groups 'Name')
            host      = @(& $resolve $row.Hosts 'Host')
            hostgroup = @(& $resolve $row.Hostgroups 'Name')
            netgroup  = @(& $resolve $row.Netgroups 'Name')
        }
        $total = @($members.Values | ForEach-Object { @($_).Count } | Measure-Object -Sum).Sum
        if ($total -eq 0) { continue }
        if (-not $PSCmdlet.ShouldProcess($name, "Add $total member(s)")) { continue }
        try {
            $outcome = Add-FreeIPAMember -Method 'netgroup_add_member' -Name $name -Members $members -Connection $connection
            $result.MembershipsApplied += $outcome.Completed
            foreach ($problem in $outcome.Errors) { $result.Errors += $problem; Write-Error $problem }
        }
        catch {
            $message = "Failed to add members to netgroup '$name': $($_.Exception.Message)"
            $result.Errors += $message
            Write-Error $message
        }
    }

    $result.Netgroups = $netgroups.ToArray()
    Write-Verbose "Netgroups: $($result.CreatedNetgroups) created, $($result.UpdatedNetgroups) updated, $($result.MembershipsApplied) memberships, $($result.Errors.Count) problems"
    if ($PassThru) { return $result }
}