Modules/Private/Reporting/Export-AZTIAsciiDocReport.ps1
|
<#
.Synopsis Export inventory data as a structured AsciiDoc report .DESCRIPTION Reads all cache files produced by the processing phase and assembles them into a single AsciiDoc document. Each category becomes a level-1 section and each module's data is rendered as an AsciiDoc table. Includes AsciiDoc admonition blocks ([TIP], [NOTE], [WARNING]) for recommendations. Suitable for Antora, Confluence, and any AsciiDoc-capable documentation system. .Link https://github.com/thisismydemo/azure-scout/Modules/Private/Reporting/Export-AZSCAsciiDocReport.ps1 .COMPONENT This PowerShell Module is part of Azure Scout (AZSC) .NOTES Version: 1.0.0 First Release Date: February 24, 2026 Authors: AzureScout Contributors #> function Export-AZSCAsciiDocReport { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$ReportCache, [Parameter(Mandatory)] [string]$File, [Parameter()] [string]$TenantID, [Parameter()] [object]$Subscriptions, [Parameter()] [ValidateSet('All', 'ArmOnly', 'EntraOnly')] [string]$Scope = 'All' ) $AdocFile = [System.IO.Path]::ChangeExtension($File, '.adoc') Write-Debug ((Get-Date -Format 'yyyy-MM-dd_HH_mm_ss') + " - AsciiDoc output file: $AdocFile") $subCount = if ($Subscriptions) { @($Subscriptions).Count } else { 0 } $genDate = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' $lines = [System.Collections.Generic.List[string]]::new() # ── Document header ────────────────────────────────────────────────── $lines.Add('= Azure Scout Report') $lines.Add('AzureScout') $lines.Add(":toc: left") $lines.Add(":toc-title: Contents") $lines.Add(":toclevels: 3") $lines.Add(":icons: font") $lines.Add(":source-highlighter: highlight.js") $lines.Add(":docdate: $genDate") $lines.Add('') $lines.Add('[NOTE]') $lines.Add('====') $lines.Add("This report was auto-generated by *AzureScout* on `$genDate`.") $lines.Add('') $lines.Add("[horizontal]") $lines.Add("Tenant ID:: $TenantID") $lines.Add("Subscriptions:: $subCount") $lines.Add("Scope:: $Scope") $lines.Add('====') $lines.Add('') # ── Discover module folders ─────────────────────────────────────────── $ParentPath = (Get-Item $PSScriptRoot).Parent.Parent $InventoryModulesPath = Join-Path $ParentPath 'Public' 'InventoryModules' $ModuleFolders = Get-ChildItem -Path $InventoryModulesPath -Directory | Sort-Object Name $CacheFiles = Get-ChildItem -Path $ReportCache -Recurse -Filter '*.json' -ErrorAction SilentlyContinue $totalResources = 0 $sectionLines = [System.Collections.Generic.List[string]]::new() foreach ($ModuleFolder in $ModuleFolders) { $FolderName = $ModuleFolder.Name $JSONFileName = "$FolderName.json" $CacheFile = $CacheFiles | Where-Object { $_.Name -eq $JSONFileName } if (-not $CacheFile) { continue } $RawJson = try { [System.IO.File]::ReadAllText($CacheFile.FullName) } catch { $null } if ([string]::IsNullOrWhiteSpace($RawJson)) { continue } $CacheData = $RawJson | ConvertFrom-Json $ModuleFiles = Get-ChildItem -Path (Join-Path $ModuleFolder.FullName '*.ps1') -ErrorAction SilentlyContinue | Sort-Object BaseName $folderHasData = $false $folderSections = [System.Collections.Generic.List[string]]::new() foreach ($Module in $ModuleFiles) { $ModName = $Module.BaseName $ModResources = $CacheData.$ModName if (-not $ModResources -or @($ModResources).Count -eq 0) { continue } $rows = @($ModResources) $totalResources += $rows.Count if (-not $folderHasData) { $folderSections.Add("== $FolderName") $folderSections.Add('') $folderHasData = $true } # Module sub-section $folderSections.Add("=== $ModName") $folderSections.Add('') $folderSections.Add("[TIP]") $folderSections.Add("====") $folderSections.Add("$($rows.Count) resource(s) found in this module.") $folderSections.Add("====") $folderSections.Add('') # Build AsciiDoc table $props = $rows[0].PSObject.Properties.Name | Where-Object { $_ -notmatch 'Tag (Name|Value)|Resource U' } if ($props.Count -gt 0) { $colSpec = ($props | ForEach-Object { '1' }) -join ',' $folderSections.Add("[%header,cols=""$colSpec""]") $folderSections.Add('|===') # Header row $folderSections.Add(($props | ForEach-Object { "| $_" }) -join ' ') foreach ($row in $rows) { $cells = $props | ForEach-Object { $v = $row.$_ if ($null -eq $v) { '' } else { [string]$v -replace '\|', '{vbar}' -replace '\r?\n', ' +' } } $folderSections.Add(($cells | ForEach-Object { "| $_" }) -join ' ') } $folderSections.Add('|===') } $folderSections.Add('') } if ($folderHasData) { foreach ($l in $folderSections) { $sectionLines.Add($l) } } } $lines.Add("_Total resources inventoried: *$totalResources*_") $lines.Add('') foreach ($l in $sectionLines) { $lines.Add($l) } # ── Footer ──────────────────────────────────────────────────────────── $lines.Add("'''") $lines.Add('') $lines.Add("[NOTE]") $lines.Add('====') $lines.Add("Generated by link:https://github.com/thisismydemo/azure-scout[AzureScout] at $genDate") $lines.Add('====') try { $lines | Out-File -FilePath $AdocFile -Encoding UTF8 -Force Write-Host "AsciiDoc report saved to: " -ForegroundColor Green -NoNewline Write-Host $AdocFile -ForegroundColor Cyan } catch { Write-Warning "Failed to write AsciiDoc report to '$AdocFile': $_" } return $AdocFile } |