LibreDevOpsHelpers.TerraformDocs/LibreDevOpsHelpers.TerraformDocs.psm1
<# ───────────────────────── TerraformDocs.psm1 ─────────────────────────── #> function Format-Terraform { [CmdletBinding()] param( [Parameter(Mandatory)][string]$CodePath ) $inv = $MyInvocation.MyCommand.Name $orig = Get-Location try { $tf = Get-Command terraform -ErrorAction Stop _LogMessage -Level INFO -Message "terraform found at '$( $tf.Source )'" -InvocationName $inv Set-Location $CodePath & terraform fmt -recursive if ($LASTEXITCODE) { throw "terraform fmt returned exit code $LASTEXITCODE" } _LogMessage -Level INFO -Message 'Terraform files formatted (fmt -recursive).' -InvocationName $inv } catch { _LogMessage -Level ERROR -Message $_.Exception.Message -InvocationName $inv throw } finally { Set-Location $orig } } ############################################################################# # Helper – format all *.tf files under the current dir (terraform fmt -recursive) ############################################################################# function Format-TerraformCode { [CmdletBinding()] param( [Parameter(Mandatory)][string]$CodePath, [string]$VariablesFile = 'variables.tf', [string]$OutputsFile = 'outputs.tf' ) $inv = $MyInvocation.MyCommand.Name # ── step 1: terraform fmt ─────────────────────────────────────────── Format-Terraform -CodePath $CodePath # ── step 2: sort variables.tf ─────────────────────────────────────── $varPath = Join-Path $CodePath $VariablesFile if (Test-Path $varPath) { $varsContent = Read-TerraformFile -Filename $varPath if (-not [string]::IsNullOrWhiteSpace($varsContent)) { $sortedVars = Format-TerraformVariables -VariablesContent $varsContent if (-not [string]::IsNullOrWhiteSpace($sortedVars)) { Write-TerraformFile -Filename $varPath -Content $sortedVars _LogMessage -Level INFO -Message "Sorted variables in $varPath" -InvocationName $inv } else { _LogMessage -Level INFO -Message "No variable blocks found to sort in $varPath, skipping write." -InvocationName $inv } } else { _LogMessage -Level INFO -Message "File $varPath is empty, skipping variable sort." -InvocationName $inv } } # ── step 3: sort outputs.tf ───────────────────────────────────────── $outPath = Join-Path $CodePath $OutputsFile if (Test-Path $outPath) { $outContent = Read-TerraformFile -Filename $outPath if (-not [string]::IsNullOrWhiteSpace($outContent)) { $sortedOut = Format-TerraformOutputs -OutputsContent $outContent if (-not [string]::IsNullOrWhiteSpace($sortedOut)) { Write-TerraformFile -Filename $outPath -Content $sortedOut _LogMessage -Level INFO -Message "Sorted outputs in $outPath" -InvocationName $inv } else { _LogMessage -Level INFO -Message "No output blocks found to sort in $outPath, skipping write." -InvocationName $inv } } else { _LogMessage -Level INFO -Message "File $outPath is empty, skipping output sort." -InvocationName $inv } } } ############################################################################# # Safe file-read ############################################################################# function Read-TerraformFile { [CmdletBinding()] param([Parameter(Mandatory)][string]$Filename) if (-not (Test-Path $Filename)) { _LogMessage -Level ERROR -Message "File not found: $Filename" -InvocationName $MyInvocation.MyCommand.Name throw "File not found: $Filename" } try { return Get-Content -Raw -LiteralPath $Filename } catch { _LogMessage -Level ERROR -Message $_.Exception.Message -InvocationName $MyInvocation.MyCommand.Name; throw } } ############################################################################# # Safe file-write ############################################################################# function Write-TerraformFile { [CmdletBinding()] param( [Parameter(Mandatory)][string]$Filename, [Parameter(Mandatory)][string]$Content ) try { $Content | Set-Content -LiteralPath $Filename } catch { _LogMessage -Level ERROR -Message $_.Exception.Message -InvocationName $MyInvocation.MyCommand.Name; throw } } ############################################################################# # Sort variables.tf blocks alphabetically by variable name ############################################################################# function Format-TerraformVariables { [CmdletBinding()] param([Parameter(Mandatory)][string]$VariablesContent) $pattern = 'variable\s+"[^"]+"\s+\{[\s\S]*?\n\}' $blocks = [regex]::Matches($VariablesContent, $pattern) | ForEach-Object { $_.Value } $sorted = $blocks | Sort-Object { ([regex]::Match($_, 'variable\s+"([^"]+)"')).Groups[1].Value } return ($sorted -join "`n`n") } ############################################################################# # Sort outputs.tf blocks alphabetically by output name ############################################################################# function Format-TerraformOutputs { [CmdletBinding()] param([Parameter(Mandatory)][string]$OutputsContent) $pattern = 'output\s+"[^"]+"\s+\{[\s\S]*?\n\}' $blocks = [regex]::Matches($OutputsContent, $pattern) | ForEach-Object { $_.Value } $sorted = $blocks | Sort-Object { ([regex]::Match($_, 'output\s+"([^"]+)"')).Groups[1].Value } return ($sorted -join "`n`n") } ############################################################################# # Generate / refresh README.md using terraform-docs ############################################################################# function Update-ReadmeWithTerraformDocs { [CmdletBinding()] param( [Parameter(Mandatory)][string]$CodePath, [string]$ReadmeFile = 'README.md' ) $inv = $MyInvocation.MyCommand.Name $orig = Get-Location try { $td = Get-Command terraform-docs -ErrorAction Stop _LogMessage -Level INFO -Message "terraform-docs found at '$( $td.Source )'" -InvocationName $inv } catch { _LogMessage -Level WARN -Message 'terraform-docs not installed – README generation skipped.' -InvocationName $inv return } Set-Location $CodePath # choose build file $build = @('build.tf', 'main.tf') | Where-Object { Test-Path $_ } | Select-Object -First 1 if (-not $build) { _LogMessage -Level WARN -Message 'No build.tf or main.tf found – README not updated.' -InvocationName $inv return } _LogMessage -Level INFO -Message "Generating README.md from $build and terraform-docs…" -InvocationName $inv '```hcl' | Set-Content $ReadmeFile Get-Content $build | Add-Content $ReadmeFile '```' | Add-Content $ReadmeFile terraform-docs markdown . | Add-Content $ReadmeFile } ############################################################################# # Export ############################################################################# Export-ModuleMember -Function ` Format-Terraform, ` Format-TerraformCode, ` Read-TerraformFile, ` Write-TerraformFile, ` Format-TerraformVariables, ` Format-TerraformOutputs, ` Update-ReadmeWithTerraformDocs |