functions/configuration/Select-PSFConfig.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
function Select-PSFConfig
{
<#
    .SYNOPSIS
        Select a subset of configuration entries and return them as objects.
     
    .DESCRIPTION
        Select a subset of configuration entries and return them as objects.
         
        This can be used to retrieve related configuration entries as a single PowerShell object.
         
        For example, assuming there are the following configuration entries:
         
        LoggingProvider.LogFile.AutoInstall
        LoggingProvider.LogFile.Enabled
        LoggingProvider.LogFile.ExcludeModules
        LoggingProvider.LogFile.ExcludeTags
        LoggingProvider.LogFile.IncludeModules
        LoggingProvider.LogFile.IncludeTags
        LoggingProvider.LogFile.InstallOptional
         
        Then this line:
        Select-PSFConfig 'LoggingProvider.LogFile.*'
         
        Will return a PSCustomObject that looks similar to this:
         
        _Name : LogFile
        _FullName : LoggingProvider.LogFile
        _Depth : 1
        _Children : {}
        AutoInstall : False
        Enabled : False
        ExcludeModules : {}
        ExcludeTags : {}
        IncludeModules : {}
        IncludeTags : {}
        InstallOptional : True
         
        This selection is recursive:
        It will group on each part of the FullName of the selected configuration entries.
        - Entries that only have children and no straight values (In the example above, that would be the first, the "LoggingProvider" node) will not be included and only return children.
        - Entries with values AND children, will have child entries included in the _Children property.
        - Even child entries of Entries with values will be returned
     
    .PARAMETER FullName
        String filter to select, which configuration entries to select on.
        Use the same value on Get-PSFConfig to see what configuration entries will be processed.
     
    .PARAMETER Depth
        Only entries at the specified depth level will be returned.
        Depth starts at "0"
        In the name 'LoggingProvider.LogFile.AutoInstall' ...
     
        - "LoggingProvider" would be depth 0
        - "LogFile" would be depth 1
        - ...
     
    .EXAMPLE
        PS C:\> Select-PSFConfig 'LoggingProvider.LogFile.*'
     
        Selects all configuration settings under 'LoggingProvider.LogFile.*', grouping the value ends as PSObject.
#>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")]
    [CmdletBinding()]
    param (
        [Alias('Name')]
        [string]
        $FullName,
        
        [int[]]
        $Depth
    )
    
    begin
    {
        function Group-Config
        {
            [CmdletBinding()]
            param (
                $Config,
                
                [int]
                $Depth
            )
            
            $grouped = $Config | Group-Object { $_.FullName.Split('.')[$Depth] }
            foreach ($group in $grouped)
            {
                if (-not $group.Name) { continue }
                $data = [ordered]@{
                    _Name = $group.Name
                    _FullName = $group.Group[0].FullName.Split('.')[0..($Depth)] -join "."
                    _Depth = $Depth
                    _Children = @()
                }
                if ($subGroups = $group.Group | Where-Object { $_.FullName.Split(".").Count -gt ($Depth + 2) })
                {
                    $data._Children = Group-Config -Config $subGroups -Depth ($Depth + 1)
                    $data._Children
                }
                
                foreach ($cfgItem in ($group.Group | Where-Object { $_.FullName.Split(".").Count -eq ($Depth + 2) }))
                {
                    $cfgName = $cfgItem.FullName -replace "^([^\.]+\.){0,$($Depth + 1)}"
                    $data[$cfgName] = $cfgItem.Value
                }
                if ($data.Keys.Count -gt 4) { [PSCustomObject]$data }
            }
        }
    }
    process
    {
        $configItems = Get-PSFConfig -FullName $FullName
        Group-Config -Config $configItems -Depth 0 | ForEach-Object {
            if (-not $Depth) { return $_ }
            if ($_._Depth -in $Depth) { $_ }
        }
    }
}