internal/functions/Save-AzOpsManagementGroupChildren.ps1
function Save-AzOpsManagementGroupChildren { <# .SYNOPSIS Recursively build/change Management Group hierarchy in file system from provided scope. .DESCRIPTION Recursively build/change Management Group hierarchy in file system from provided scope. .PARAMETER Scope Scope to discover - assumes [AzOpsScope] object .PARAMETER StatePath The root path to where the entire state is being built in. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .EXAMPLE > Save-AzOpsManagementGroupChildren -Scope (New-AzOpsScope -scope /providers/Microsoft.Management/managementGroups/contoso) Discover Management Group hierarchy from scope .INPUTS AzOpsScope .OUTPUTS Management Group hierarchy in file system #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType()] param ( [Parameter(Mandatory = $true)] $Scope, [string] $StatePath = (Get-PSFConfigValue -FullName 'AzOps.Core.State') ) process { Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Starting' Invoke-PSFProtectedCommand -ActionString 'Save-AzOpsManagementGroupChildren.Creating.Scope' -Target $Scope -ScriptBlock { $scopeObject = New-AzOpsScope -Scope $Scope -StatePath $StatePath -ErrorAction SilentlyContinue -Confirm:$false } -EnableException $true -PSCmdlet $PSCmdlet if (-not $scopeObject) { return } # In case -WhatIf is used Write-PSFMessage -String 'Save-AzOpsManagementGroupChildren.Processing' -StringValues $scopeObject.Scope # Construct all file paths for scope $scopeStatepath = $scopeObject.StatePath $statepathFileName = [IO.Path]::GetFileName($scopeStatepath) $statepathDirectory = [IO.Path]::GetDirectoryName($scopeStatepath) $statepathScopeDirectory = [IO.Directory]::GetParent($statepathDirectory).ToString() $statepathScopeDirectoryParent = [IO.Directory]::GetParent($statepathScopeDirectory).ToString() Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Data.StatePath' -StringValues $scopeStatepath Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Data.FileName' -StringValues $statepathFileName Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Data.Directory' -StringValues $statepathDirectory Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Data.ScopeDirectory' -StringValues $statepathScopeDirectory Write-PSFMessage -Level Debug -String 'Save-AzOpsManagementGroupChildren.Data.ScopeDirectoryParent' -StringValues $statepathScopeDirectoryParent # If file is found anywhere in "AzOps.Core.State", ensure that it is at the right scope or else it doesn't matter if (Get-ChildItem -Path $Statepath -File -Recurse -Force | Where-Object Name -eq $statepathFileName) { # If the file is found in AzOps State $exisitingScopePath = (Get-ChildItem -Path $Statepath -File -Recurse -Force | Where-Object Name -eq $statepathFileName).Directory # Looking at parent of parent if AutoGeneratedTemplateFolderPath is sub-directory, looking for parent (scope folder) of parent (actual parent in Azure) if ( ((Get-PSFConfigValue -FullName 'AzOps.Core.AutoGeneratedTemplateFolderPath') -notin '.') -and $exisitingScopePath.Parent.Parent.FullName -ne $statepathScopeDirectoryParent) { if ($exisitingScopePath.Parent.FullName -ne $statepathScopeDirectoryParent) { Write-PSFMessage -String 'Save-AzOpsManagementGroupChildren.Moving.Source' -StringValues $exisitingScopePath Move-Item -Path $exisitingScopePath.Parent -Destination $statepathScopeDirectoryParent -Force Write-PSFMessage -String 'Save-AzOpsManagementGroupChildren.Moving.Destination' -StringValues $statepathScopeDirectoryParent } } # Files might be at the right scope but not in right AutoGeneratedTemplateFolderPath e.g. when AutoGeneratedTemplateFolderPath is changed. if (-not (Test-Path $statepathDirectory)) { New-Item -Path $statepathDirectory -ItemType Directory -Force | out-null } # For all the files in AutoGeneratedTemplateFolderPath directory, only moving files that are auto generated Get-ChildItem -Path (Get-ChildItem -Path $Statepath -File -Recurse -Force | Where-Object Name -eq $statepathFileName).Directory -File -Filter 'Microsoft.*' | Move-Item -Destination $statepathDirectory -Force } switch ($scopeObject.Type) { managementGroups { ConvertTo-AzOpsState -Resource ($script:AzOpsAzManagementGroup | Where-Object { $_.Name -eq $scopeObject.managementgroup }) -ExportPath $scopeObject.statepath -StatePath $StatePath foreach ($child in $script:AzOpsAzManagementGroup.Where{ $_.Name -eq $scopeObject.managementgroup }.Children) { if ($child.Type -eq '/subscriptions') { if ($script:AzOpsSubscriptions.id -contains $child.Id) { Save-AzOpsManagementGroupChildren -Scope $child.Id -StatePath $StatePath } else { Write-PSFMessage -String 'Save-AzOpsManagementGroupChildren.Subscription.NotFound' -StringValues $child.Name } } else { Save-AzOpsManagementGroupChildren -Scope $child.Id -StatePath $StatePath } } } subscriptions { ConvertTo-AzOpsState -Resource ($script:AzOpsAzManagementGroup.children | Where-Object Name -eq $scopeObject.name) -ExportPath $scopeObject.statepath -StatePath $StatePath } } } } |