Created
December 24, 2017 03:59
-
-
Save midacts/6f66e3b9617b81863588ce4c9c64ddc3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function New-VesterConfig { | |
<# | |
.SYNOPSIS | |
Generates a Vester config file from settings in your existing VMware environment. | |
.DESCRIPTION | |
New-VesterConfig is designed to be a quick way to get started with Vester. | |
Vester needs one config file for each vCenter server it interacts with. To | |
help speed up this one-time creation process, New-VesterConfig uses PowerCLI | |
to pull current values from your environment to store in the config file. | |
You'll be prompted with the list of Clusters/Hosts/VMs/etc. discovered, and | |
asked to choose one of each type to use as a baseline; i.e. "all my other | |
hosts should be configured like this one." Those values are displayed | |
interactively, and you can manually edit them as desired. | |
Optionally, advanced users can use the -Quiet parameter. This suppresses | |
all host output and prompts. Instead, values are pulled from the first | |
Cluster/Host/VM/etc. found alphabetically. Manual review afterward of the | |
config file is strongly encouraged if using the -Quiet parameter. | |
It outputs a single Config.json file at \Vester\Configs, which may require | |
admin rights. Optionally, you can use the -OutputFolder parameter to | |
specify a different folder to store the Config.json file. | |
.EXAMPLE | |
New-VesterConfig | |
Ensures that you are connected to only one vCenter server. | |
Based on all Vester test files found in '\Vester\Tests', the command | |
discovers values from your environment and displays them, occasionally | |
prompting for a selection of which cluster/host/etc. to use. | |
Outputs a new Vester config file to '\Vester\Configs\Config.json', | |
which may require admin rights. | |
.EXAMPLE | |
New-VesterConfig -Quiet -OutputFolder "$env:USERPROFILE\Desktop" | |
-Quiet suppresses all host output and prompts, instead pulling values | |
from the first cluster/host/etc. found alphabetically. | |
Upon completion, Config.json will be created on your Desktop. | |
.NOTES | |
This command relies on the Pester and PowerCLI modules for testing. | |
"Get-Help about_Vester" for more information. | |
.LINK | |
https://wahlnetwork.github.io/Vester | |
.LINK | |
https://github.com/WahlNetwork/Vester | |
#> | |
[CmdletBinding()] | |
param ( | |
# Select a folder to create a new Config.json file inside | |
[Parameter(Mandatory = $False)] | |
[ValidateScript({Test-Path $_ -PathType Container})] | |
[object]$OutputFolder = "$(Split-Path -Parent $PSScriptRoot)\Configs", | |
[Parameter(Mandatory = $False)] | |
[string]$Datacenter = '*', | |
[Parameter(Mandatory = $False)] | |
[string]$Cluster = '*', | |
[Parameter(Mandatory = $False)] | |
[string]$DatastoreCluster = '*', | |
[Parameter(Mandatory = $False)] | |
[string]$VMHost = '*', | |
[Parameter(Mandatory = $False)] | |
[string]$VM = '*', | |
[Parameter(Mandatory = $False)] | |
[string]$VDS = '*' | |
) | |
# Must have only one vCenter connection open | |
# Potential future work: loop through all vCenter connections | |
If ($DefaultVIServers.Count -lt 1) { | |
Write-Warning 'Please connect to vCenter before running this command.' | |
throw 'A single connection with Connect-VIServer is required.' | |
} ElseIf ($DefaultVIServers.Count -gt 1) { | |
Write-Warning 'Vester config files are designed to be unique to each vCenter server.' | |
Write-Warning 'Please connect to only one vCenter before running this command.' | |
Write-Warning "Current connections: $($DefaultVIServers -join ' / ')" | |
throw 'A single connection with Connect-VIServer is required.' | |
} | |
Write-Verbose "vCenter: $($DefaultVIServers.Name)" | |
# TODO: Make this a param? Or keep hardcoded? | |
Write-Verbose "Assembling Vester files within $(Split-Path -Parent $PSScriptRoot)\Tests\" | |
$GetVesterTest = "$(Split-Path -Parent $PSScriptRoot)\Tests\" | Get-VesterTest -Simple | |
# Appending to a list is faster than rebuilding an array | |
$VesterTestSuite = New-Object 'System.Collections.Generic.List[PSCustomObject]' | |
# For each *.Vester.ps1 file found | |
$GetVesterTest | ForEach-Object { | |
# Do the necessary Split-Path calls once and save them for later | |
$TestObj = [PSCustomObject]@{ | |
Full = $_ | |
Parent = Split-Path (Split-Path $_ -Parent) -Leaf | |
Leaf = Split-Path $_ -Leaf | |
} | |
$VesterTestSuite.Add($TestObj) | |
} | |
# Grabs the high level test scopes. | |
# Under Vester\Test the folders named: Cluster, DSCluster, Host, etc | |
$ScopeList = ($VesterTestSuite | Select-Object -Property Parent -Unique).Parent | |
Write-Verbose "Scopes supplied by test files: $($ScopeList -join ' | ')" | |
# Builds out the config | |
$config = [ordered]@{} | |
$config.vcenter = @{vc = $DefaultVIServers.Name} | |
$config.scope = [ordered]@{ | |
datacenter = $Datacenter | |
cluster = $Cluster | |
dscluster = $DatastoreCluster | |
host = $VMHost | |
vm = $VM | |
vds = $VDS | |
} | |
# Gathers the supplied inventory items | |
Write-Verbose "Gathering inventory objects from $($DefaultVIServers.Name)" | |
$vCenter = $DefaultVIServers.Name | |
$DatacenterObject = Get-Datacenter -Name $config.scope.datacenter -Server $vCenter | |
$ClusterObject = Get-Cluster -Location $DatacenterObject -Name $config.scope.cluster | |
$DSClusterObject = $DatacenterObject | Get-DatastoreCluster -Name $config.scope.dscluster | |
$VMHostObject = $ClusterObject | Get-VMHost -Name $config.scope.host | |
$VMObject = $ClusterObject | Get-VM -Name $config.scope.vm | |
$NetworkObject = $DatacenterObject | Get-VDSwitch -Name $config.scope.vds -ErrorAction Stop | |
# Group tests by their scope | |
ForEach ($Scope in $ScopeList) { | |
Write-Verbose "Processing all tests for scope $Scope" | |
# Loop through each test file applicable in the current scope | |
# Couldn't resist calling each file a Vest. Sorry, everyone | |
ForEach ($Vest in $VesterTestSuite | Where-Object Parent -eq $Scope) { | |
Write-Verbose "Processing test file $($Vest.Leaf)" | |
# Import all variables from the current .Vester.ps1 file | |
. $Vest.Full | |
$Object = switch ($Scope) { | |
'vCenter' {$vCenter} | |
'Datacenter' {$DatacenterObject} | |
'Cluster' {$ClusterObject} | |
'DSCluster' {$DSClusterObject} | |
'Host' {$VMHostObject} | |
'VM' {$VMObject} | |
'Network' {$NetworkObject} | |
# If not scoped properly, don't know what object to check | |
Default {$null} | |
} | |
# TODO: Should probably offload this to a private function | |
$CfgLine = (Select-String -Path $Vest.Full -Pattern '\$cfg') -replace '.*\:[0-9]+\:','' | |
$CfgLine -match '.*\$cfg\.([a-z]+)\.([a-z]+)$' | Out-Null | |
# Run the $Actual script block, storing the result in $Result | |
If ($Object -and ($Result = & $Actual) -ne $null) { | |
# Call module private function Set-VesterConfigValue to add the entry | |
Set-VesterConfigValue -Value ($Result -as $Type) | |
} Else { | |
# Inventory $Object doesn't exist, or $Actual returned nothing | |
# Populate with null value; Invoke-Vester will skip this test | |
Set-VesterConfigValue -Value $null | |
} #if $Object and $Result | |
} #foreach $Vest | |
# Formats the results for this scope in an ordered hashtable | |
Write-Host '' | |
Write-Host ' # Config values for scope ' -NoNewline | |
Write-Host "$Scope" -ForegroundColor Green | |
# Only gets the enumerator if values exist | |
$Sorted = If($config.$Scope){ $config.$Scope.GetEnumerator() | Sort-Object Name } | |
$Sorted | |
$config.$Scope = [ordered]@{} | |
$Sorted | Foreach-Object { $config.$Scope.Add($_.Name, $_.Value) } | |
} #foreach $Scope | |
Write-Verbose "Creating config file at $OutputFolder\Config.json" | |
Try { | |
$config | ConvertTo-Json | Out-File $OutputFolder\Config.json -ErrorAction Stop | |
Write-Host "`nConfig file created at " -ForegroundColor Green -NoNewline | |
Write-Host "$OutputFolder\Config.json" | |
Write-Host 'Edit the file manually to change any displayed values.' | |
} Catch { | |
Write-Warning "`nFailed to create config file at $OutputFolder\Config.json" | |
Write-Warning 'Have you tried running PowerShell as an administrator?' | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment