De afgelopen tijd ben ik bezig geweest om te kijken of het mogelijk is om automatisch documentatie te creëren door middel van Powershell. In dit specifieke geval ging het over de inrichting van Ivanti Automation Manager welke door ons ingezet is om een compleet geautomatiseerde omgeving uit te kunnen rollen.
Door in een dergelijk geval ook de documentatie te automatiseren, geeft ons dit sneller en beter inzicht in wat er is ingesteld in de software en kunnen we zeker zijn dat de documentatie ook altijd klopt met wat er is ingesteld.
We hebben in dit geval ervoor gekozen om de inrichting naar een Excel file (of als keuze een CSV) te laten schrijven.
In deze blog wil ik jullie een beeld geven van hoe we dit opgebouwd hebben.
De documentatie
Om de documentatie automatisch te creëren maken we, in dit geval, gebruik van de mogelijkheid om building blocks te exporteren uit Ivanti Automation Manager. Hieruit komt een XML met alle instellingen.
Het is natuurlijk oom mogelijk om op andere manieren data op te halen dan via XML. Uiteindelijk is het vooral belangrijk dat je de uiteindelijk data die je nodig hebt voor je documentatie kan vertalen naar tabellen of een andere format die voor jou documentatie handig is.
De voorwaarde van Automatisch documenteren, is dat de plek waar de informatie vandaan gehaald wordt, wel voldoende is ingevuld en dat de informatie ook nuttig en bruikbaar is. In ons geval van Ivanti Automation Manager, hebben we het description veld gebruikt, om extra informatie in te vullen. Hiermee hebben we voldoende informatie voor de documentatie, naast de andere standaard informatie die er al in zitten.
Het bouwen van het script
De eerste stap die we zetten is het creëren van een functie, in dit geval noemen we de functie Invoke-IAM-Documentation, waarbij IAM staat voor Ivanti Automation Manager.
We bepalen de parameters welke we willen gebruiken binnen de functie en we bepalen of de parameters verplicht zijn of niet.
functionInvoke-IWC-Documentation{
[CmdletBinding()]
param(
[Parameter(Mandatory= $True)]
[string]$ExportPath,
[string]$BB,
[string]$Excel,
[Parameter(Mandatory= $false)]
[switch]$CSV
)
Vervolgens bouwen we het eerste deel van het script op. Hier bepalen we de zaken als de “workingdir” welke met de variabele “exportpath”wordt gevuld. Ook bepalen we hier op dezelfde manier, de plaats waar het bestand wordt opgeslagen en de locatie van de XML file die we willen inlezen.
Zoals je kunt zien, wordt de inhoudt van de XML file in de variabele $XML geplaatst. Er wordt ook gekeken of de CSV, dan wel de Excel File, reeds aanwezig zijn. Als dat het geval is dan worden deze eerst verwijderd.
$workingdir= $exportpath
$Output= $Excel
$XML= $BB
[xml]$xml= Get-Content"$XML"
$Excelfile= "$workingdir$Output"
$RunbookCSVFile= "$workingdirrunbook.csv"
if(Test-Path$RunbookCSVFile) { Remove-Item-Path $RunbookCSVFile}
$ProjectCSVFile= "$workingdirproject.csv"
if(Test-Path$ProjectCSVFile) { Remove-Item-Path $ProjectCSVFile}
$ModulesCSVFile= "$workingdirmodules.csv"
if(Test-Path$ModulesCSVFile) { Remove-Item-Path $ModulesCSVFile}
$TasksCSVFile= "$workingdirtasks.csv"
if(Test-Path$TasksCSVFile) { Remove-Item-Path $TasksCSVFile}
$ParametersCSVFile= "$workingdirparamaters.csv"
if(Test-Path$ParametersCSVFile) { Remove-Item-Path $ParametersCSVFile}
if(Test-Path$Excelfile) { Remove-Item-Path $Excelfile}
Nu gaan we de juiste modules inladen. In dit geval maken we gebruik van PSExcel, om de mogelijkheid te creëren direct naar een Excel file te kunnen exporteren. We controleren of deze al is geïnstalleerd, zo niet dan wordt deze alsnog geïnstalleerd en vervolgens ingeladen.
Het voordeel hiervan ten opzichte van een CSV export, is dat je kan werken met worksheets en je veel meer mogelijkheden hebt om direct je Excel file de juiste format mee te geven die je zou willen hebben.
$EXmodule= Get-Modulepsexcel
if(!$EXmodule) {
Install-PackageProvider-Name NuGet -MinimumVersion 2.8.5.201-Force -scope CurrentUser
Install-ModulePSExcel -Force -Scope CurrentUser
}
Import-ModulePSExcel -Force
Data uitlezen
Nu we alle voorbereidingen in het script hebben getroffen, kunnen we de data uit gaan lezen uit de XML en deze in een tabel gaan plaatsen.
Het eerste wat willen, is het Runbook die we hebben aangemaakt, uitlezen en omzetten naar een Excel Worksheet.
Dit doen we door in de XML eerst naar de juiste locatie te gaan. Dit zie je in de onderstaande regel. We gaan dus binnen de XML naar de runbook informatie toe en zetten dit in de variabele $Runbooks.
$Runbooks= $xml.AutomationManager.buildingblock.runbooks.runbook.properties
Nu dat we dit specifieke deel in een variabele hebben gezet, kunnen we verder de data uit gaan lezen.
We maken als eerste de twee variabelen die we gebruiken voor de tabellen leeg, dit om zeker te zijn dat hier geen oude data van een vorige run in de output terecht komt.
$Runbooktable= @()
$Runbooktotal= @()
Vervolgens maken we een foreach aan, welke door de aanwezige runbooks gaat in de variabele $Runbooks en elk runbook die hij vindt gaat plaatsen in een tabel.
$runbooktable wordt gebruikt voor het bouwen van de tabel.
Om specifieke data op te halen van de runbook, weten we dat we met $runbook alle waardes op kunnen halen van dat runbook. Door nu gebruik te maken van bijvoorbeeld $runbook.name, kunnen we dus in dit geval de naam van het runbook ophalen.
Je kan simpel testen welke gegevens er allemaal op te halen zijn door $runbooks op te roepen en te kijken welke velden daar allemaal onder zitten. Je zal dan zaken als Name, Enabled en Description tegenkomen, maar ook een aantal andere velden die bruikbaar kunnen zijn.
Op deze manier halen we de data die wij willen hebben uit de XML en zetten dit in onze tabel doormiddel van het onderstaande stuk script.
foreach($Runbookin$Runbooks) {
#DATA CSV
$runbooktable= New-ObjectPSobject
$runbooktable| Add-Member-Type NoteProperty -Name Name -Value $runbook.name
$runbooktable| Add-Member-Type NoteProperty -Name Enabled -Value $runbook.enabled
$runbooktable| Add-Member-Type NoteProperty -Name Description -Value $runbook.description
$runbooktable| Add-Member-Type NoteProperty -Name Projects -Value $runbook.properties.jobs.job.count
$Runbooktotal+= $Runbooktable
}
CSV-export
Nu bepalen we nog of we CSV export willen of niet. Dit kan je als variabele opgeven in de functie. Als dit niet is opgegeven, dan wordt er een export van de Tabel naar worksheet geschreven, in dit geval “Runbooks”. Hierbij wordt gelijk de tabel in de gewenste tabel style gezet.
if($CSV) {
$Runbooktotal| Export-Csv-Append -NoTypeInformation -Delimiter ';'-Path $RunbookCSVFile
}
$Runbooktotal| Export-XLSX-Path $Excelfile-AutoFit -Table -TableStyle Medium2 -WorksheetName "Runbooks"
Deze stukjes script kan je vervolgens herhalen op dezelfde manier voor een Project, Module of taken. Maar eventuele ook voor andere informatie die je eruit zou willen halen.
Uiteindelijk krijg je hier een nette Excel file uit. Deze geeft je in één overzicht alle informatie die je wilt hebben over de runbooks, projecten, modules e.d.
Andere software
We hebben dit deel gebouwd voor Ivanti Automation Manager, echter dit zou je voor elke software kunnen doen. Dit hoeft niet eens een XML te zijn. Het kan elke vorm van data zijn, zolang je dit maar in de juiste format kan krijgen binnen je script in de variabele, zal dit nooit een probleem mogen zijn.
Word
Het is ook mogelijk om dit in Word te doen. Dit is echter wel wat lastiger, je zal hier met COM objecten moeten gaan werken om dit voor elkaar te gaan krijgen.
Onderstaand is bijvoorbeeld een manier waarop je een Word document kan aanmaken.
## open word document
$word= New-Object-ComObject "Word.application"
$word.visible= $true
$doc= $word.Documents.Add()
$doc.Activate()
Vervolgens kan je met onderstaande regels een stukje format geven aan je word document. In de regel $word.selection.TypeText kan je vervolgens een stuk tekst in je word document krijgen met de daarvoor opgegeven format.
$word.Selection.Font.Name= "Calibri"
$word.Selection.Font.Size= "12"
$word.Selection.Font.Bold= 1
$word.selection.ParagraphFormat.Alignment= 1
$word.Selection.TypeText("$($Module.properties.name)")
$word.Selection.TypeParagraph()
Hoewel dit nog een stuk is waar ik verder mee aan het experimenteren ben, met als doel om uiteindelijk ook complete Word documenten te kunnen bouwen, geeft dit in ieder geval alvast een beeld van hoe je dit zou kunnen doen.