add function helpers and update readme

This commit is contained in:
Adam Rudell 2021-09-15 13:30:29 -05:00
Родитель 58c472e875
Коммит 8f7386bfa7
7 изменённых файлов: 306 добавлений и 16 удалений

Просмотреть файл

@ -17,7 +17,7 @@ param (
[Parameter(Mandatory = $true)]
[ArgumentCompleter({
$possibleValues = Get-ChildItem -Path "$PSScriptRoot\templates\*" -Include *.ps1 | Select-Object -ExpandProperty Name
$possibleValues = Get-ChildItem -Path "$PSScriptRoot\templates\module\*" -Include *.ps1 | Select-Object -ExpandProperty Name
return $possibleValues | ForEach-Object { $_ }
})]
[System.String]$Template,
@ -29,6 +29,7 @@ param (
$ErrorActionPreference = 'Stop'
# verify the function name matches approved verbs
$FunctionName = (Get-Culture).TextInfo.ToTitleCase("$FunctionName".tolower())
$verb = $FunctionName.Split('-')[0]
if($verb -inotin (Get-Verb).Verb){
$publicDocURL = 'https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands'
@ -36,9 +37,6 @@ if($verb -inotin (Get-Verb).Verb){
return
}
# retrieve the template that will be used
$templatePath = Get-Item -Path "$PSScriptRoot\templates\$($Template)"
# generate the filepath where the function will be saved
if($IsPublic){
$subPath = 'public'
@ -47,10 +45,11 @@ else {
$subPath = 'private'
}
$relativePath = ("src\modules\$($Module)\$($subPath)\$($FunctionName).ps1")
$templatePath = Get-Item -Path "$PSScriptRoot\templates\module\$($Template)"
$relativePath = "src\modules\{0}\{1}\{2}.ps1" -f $Module, $subPath, $FunctionName
$destinationPath = Join-Path -Path "$PSScriptRoot\..\..\" -ChildPath $relativePath
$allFunctionFiles = (Get-ChildItem -Path "$PSScriptRoot\..\..\src\modules\*" -Include *.ps1 -Recurse)
$allFunctionFiles = (Get-ChildItem -Path "$PSScriptRoot\..\..\src\*" -Include *.ps1 -Recurse)
$duplicateFunction = $allFunctionFiles | Where-Object {$_.BaseName -ieq $FunctionName}
if($duplicateFunction){
"{0} already exists under {1}. Specify a new function name to prevent dot sourcing conflicts" -f $FunctionName, $duplicateFunction.FullName | Write-Host -ForegroundColor:Yellow
@ -60,10 +59,11 @@ if($duplicateFunction){
# create the function file based off template and replace the function name within the file
$newFunctionFile = Copy-Item -Path $templatePath -Destination $destinationPath -PassThru
if($newFunctionFile){
"Successfully created {0}" -f $newFunctionFile.FullName | Write-Host
$content = Get-Content -Path $newFunctionFile.FullName
$newContent = $content -Replace 'VERB-NAME', $FunctionName
$newContent | Set-Content -Path $newFunctionFile.FullName
"Successfully created {0}" -f $newFunctionFile.FullName | Write-Host
}
else {
"Unable to create new function file {0}" | Write-Host -ForegroundColor:Yellow

Просмотреть файл

@ -0,0 +1,64 @@
<#
.SYNOPSIS
Creates new function file based off template
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[System.String]$FunctionName,
[Parameter(Mandatory = $true)]
[ArgumentCompleter({
$possibleValues = Get-ChildItem -Path "$PSScriptRoot\..\..\src\health" -Directory | Select-Object -ExpandProperty Name
return $possibleValues | ForEach-Object { $_ }
})]
[System.String]$Module,
[Parameter(Mandatory = $true)]
[ArgumentCompleter({
$possibleValues = Get-ChildItem -Path "$PSScriptRoot\templates\health\*" -Include *.ps1 | Select-Object -ExpandProperty Name
return $possibleValues | ForEach-Object { $_ }
})]
[System.String]$Template
)
$ErrorActionPreference = 'Stop'
# verify the function name matches approved verbs
$FunctionName = (Get-Culture).TextInfo.ToTitleCase("$FunctionName".tolower())
$verb = $FunctionName.Split('-')[0]
if($verb -ine ('Test')){
"Please ensure that you are using the verb 'Test' for your function name when creating health validation function." | Write-Host -ForegroundColor:Yellow
return
}
# generate the filepath where the function will be saved
$templatePath = Get-Item -Path "$PSScriptRoot\templates\health\$($Template)"
$relativePath = "src\health\{0}\{1}.ps1" -f $Module, $FunctionName
$destinationPath = Join-Path -Path "$PSScriptRoot\..\..\" -ChildPath $relativePath
$allFunctionFiles = (Get-ChildItem -Path "$PSScriptRoot\..\..\src\*" -Include *.ps1 -Recurse)
$duplicateFunction = $allFunctionFiles | Where-Object {$_.BaseName -ieq $FunctionName}
if($duplicateFunction){
"{0} already exists under {1}. Specify a new function name to prevent dot sourcing conflicts" -f $FunctionName, $duplicateFunction.FullName | Write-Host -ForegroundColor:Yellow
return
}
# create the function file based off template and replace the function name within the file
$newFunctionFile = Copy-Item -Path $templatePath -Destination $destinationPath -PassThru
if($newFunctionFile){
$content = Get-Content -Path $newFunctionFile.FullName
$newContent = $content -Replace 'VERB-NAME', $FunctionName
$newContent | Set-Content -Path $newFunctionFile.FullName
"Successfully created {0}" -f $newFunctionFile.FullName | Write-Host
}
else {
"Unable to create new function file {0}" | Write-Host -ForegroundColor:Yellow
}
$ErrorActionPreference = 'Continue'

Просмотреть файл

@ -0,0 +1,55 @@
<#
.SYNOPSIS
Creates new function file based off template
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[System.String]$FunctionName,
[Parameter(Mandatory = $true)]
[ArgumentCompleter({
$possibleValues = Get-ChildItem -Path "$PSScriptRoot\templates\knownIssue\*" -Include *.ps1 | Select-Object -ExpandProperty Name
return $possibleValues | ForEach-Object { $_ }
})]
[System.String]$Template
)
$ErrorActionPreference = 'Stop'
# verify the function name matches approved verbs
$FunctionName = (Get-Culture).TextInfo.ToTitleCase("$FunctionName".tolower())
if($FunctionName -inotlike "Test-SdnKI*"){
"Please ensure that you are prefixing your function name wtih 'Test-SdnKI' when creating known issue check." | Write-Host -ForegroundColor:Yellow
return
}
# generate the filepath where the function will be saved
$templatePath = Get-Item -Path "$PSScriptRoot\templates\knownIssue\$($Template)"
$relativePath = "src\knownIssues\{0}.ps1" -f $FunctionName
$destinationPath = Join-Path -Path "$PSScriptRoot\..\..\" -ChildPath $relativePath
$allFunctionFiles = (Get-ChildItem -Path "$PSScriptRoot\..\..\src\*" -Include *.ps1 -Recurse)
$duplicateFunction = $allFunctionFiles | Where-Object {$_.BaseName -ieq $FunctionName}
if($duplicateFunction){
"{0} already exists under {1}. Specify a new function name to prevent dot sourcing conflicts" -f $FunctionName, $duplicateFunction.FullName | Write-Host -ForegroundColor:Yellow
return
}
# create the function file based off template and replace the function name within the file
$newFunctionFile = Copy-Item -Path $templatePath -Destination $destinationPath -PassThru
if($newFunctionFile){
$content = Get-Content -Path $newFunctionFile.FullName
$newContent = $content -Replace 'VERB-NAME', $FunctionName
$newContent | Set-Content -Path $newFunctionFile.FullName
"Successfully created {0}" -f $newFunctionFile.FullName | Write-Host
}
else {
"Unable to create new function file {0}" | Write-Host -ForegroundColor:Yellow
}
$ErrorActionPreference = 'Continue'

Просмотреть файл

@ -0,0 +1,75 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
function VERB-NAME {
<#
.SYNOPSIS
Validate that the configurationState and provisioningState is Success
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[Uri]$NcUri = $Global:SdnDiagnostics.EnvironmentInfo.NcUrl,
[Parameter(Mandatory = $false)]
[System.String[]]$ComputerName = $global:SdnDiagnostics.EnvironmentInfo.MUX,
[Parameter(Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$NcRestCredential = [System.Management.Automation.PSCredential]::Empty
)
try {
"Validating <DESCRIPTION>" | Trace-Output
$config = Get-SdnRoleConfiguration -Role:SoftwareLoadBalancer
if($null -eq $NcUri){
throw New-Object System.NullReferenceException("Please specify NcUri parameter or execute Get-SdnInfrastructureInfo to populate environment details")
}
if($null -eq $ComputerName){
throw New-Object System.NullReferenceException("Please specify ComputerName parameter or execute Get-SdnInfrastructureInfo to populate environment details")
}
# if Credential parameter not defined, check to see if global cache is populated
if(!$PSBoundParameters.ContainsKey('Credential')){
if($Global:SdnDiagnostics.Credential){
$Credential = $Global:SdnDiagnostics.Credential
}
}
# if NcRestCredential parameter not defined, check to see if global cache is populated
if(!$PSBoundParameters.ContainsKey('NcRestCredential')){
if($Global:SdnDiagnostics.NcRestCredential){
$NcRestCredential = $Global:SdnDiagnostics.NcRestCredential
}
}
$status = 'Success'
$arrayList = [System.Collections.ArrayList]::new()
<#
INSERT LOGIC DETECTION HERE
IF FAILURE DETECTED, SET STATUS TO FAILURE
$status = 'Failure'
# ADD TO ARRAY LIST WITH ANY PROPERTIES THAT YOU WANT TO RETURN
#>
return [PSCustomObject]@{
Status = $status
Properties = $arrayList
}
}
catch {
"{0}`n{1}" -f $_.Exception, $_.ScriptStackTrace | Trace-Output -Level:Error
}
}

Просмотреть файл

@ -0,0 +1,75 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
function VERB-NAME {
<#
.SYNOPSIS
Validate that the configurationState and provisioningState is Success
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[Uri]$NcUri = $Global:SdnDiagnostics.EnvironmentInfo.NcUrl,
[Parameter(Mandatory = $false)]
[System.String[]]$ComputerName = $global:SdnDiagnostics.EnvironmentInfo.MUX,
[Parameter(Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$NcRestCredential = [System.Management.Automation.PSCredential]::Empty
)
try {
"Validating <DESCRIPTION>" | Trace-Output
$config = Get-SdnRoleConfiguration -Role:SoftwareLoadBalancer
if($null -eq $NcUri){
throw New-Object System.NullReferenceException("Please specify NcUri parameter or execute Get-SdnInfrastructureInfo to populate environment details")
}
if($null -eq $ComputerName){
throw New-Object System.NullReferenceException("Please specify ComputerName parameter or execute Get-SdnInfrastructureInfo to populate environment details")
}
# if Credential parameter not defined, check to see if global cache is populated
if(!$PSBoundParameters.ContainsKey('Credential')){
if($Global:SdnDiagnostics.Credential){
$Credential = $Global:SdnDiagnostics.Credential
}
}
# if NcRestCredential parameter not defined, check to see if global cache is populated
if(!$PSBoundParameters.ContainsKey('NcRestCredential')){
if($Global:SdnDiagnostics.NcRestCredential){
$NcRestCredential = $Global:SdnDiagnostics.NcRestCredential
}
}
$issueDetected = $false
$arrayList = [System.Collections.ArrayList]::new()
<#
INSERT LOGIC DETECTION HERE
IF FAILURE DETECTED, SET VARIABLE TO $TRUE
$issueDetected = $true
# ADD TO ARRAY LIST WITH ANY PROPERTIES THAT YOU WANT TO RETURN
#>
return [PSCustomObject]@{
Result = $issueDetected
Properties = $arrayList
}
}
catch {
"{0}`n{1}" -f $_.Exception, $_.ScriptStackTrace | Trace-Output -Level:Error
}
}

Просмотреть файл

@ -16,23 +16,32 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
When contributing to this project, ensure you:
1. Review existing functions already available and reuse where possible.
1. Functions should be placed under `src\modules\[ModuleName]\[Private | Public]\Verb-FunctionName.ps1`.
- Function name should match the file name.
- Limit one function per file.
- Ensure that the file name is added to `src\SDNDiagnostics.psm1` so it is dot sourced on module import.
- Use [Approved Verbs for PowerShell Commands](https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands).
1. If your function should be exported and available after module import, be sure to add your function to the export list in `src\SDNDiagnostics.psd1` under `FunctionsToExport`.
1. Return native .NET objects whenever possible.
1. Rarely should you return from a function with format-table, format-list, etc.. If they do, they should use the PowerShell verb `Show`.
1. Environments that this module run on may be in a broken or inconcistent state, so defensive coding techniques should be leveraged.
1. Leverage `$Global:SdnDiagnostics` for caching when appropriate.
## Creating Core Modules
When creating core functions:
1. Functions should be placed under `src\modules\[ModuleName]\[Private | Public]\Verb-FunctionName.ps1`.
- Function name should match the file name.
- Limit one function per file.
- Ensure that the file name is added to `src\SDNDiagnostics.psm1` so it is dot sourced on module import.
- Use [Approved Verbs for PowerShell Commands](https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands).
1. If your function should be exported and available after module import, be sure to add your function to the export list in `src\SdnDiagnostics.psd1` under `FunctionsToExport`.
To help ensure consistency, leverage `.build\utilities\create-function.ps1` to help create your functions. This will create a `.ps1` file off the specified template and place into the appropriate module directory. Example:
```powershell
.\create-core-function.ps1 -FunctionName 'Disable-RasGatewayTracing' -Module Gateway -Template basic_template.ps1 -IsPublic
```
## Creating Health Validation Tests
When creating a health validation test, ensure you:
1. Create the `ps1` file under `src\health\[role]\` as the name of the validation test. e.g. `Test-SdnServerHealth.ps1`
1. Function should return a PSCustomObject that contains the following format:
```
```powershell
# $status should contain either 'Success' or 'Failure'
# $properties will contain any related information in scenario of 'Failure' status
else {
@ -46,10 +55,16 @@ When creating a health validation test, ensure you:
- `Debug-SdnFabricInfrastructure` will automatically pick up tests under the `src\health` directory.
1. The infrastructure information can be retrieved from global cache at `$Global:SdnDiagnostics`
To help ensure consistency, leverage `.build\utilities\create-health-function.ps1` to help create your functions. This will create a `.ps1` file off the specified template and place into the appropriate module under `src\health`. Example:
```powershell
.\create-health-function.ps1 -FunctionName 'Test-SdnLoadBalancerMuxOnline' -Module SoftwareLoadBalancer -Template basic_health_template.ps1
```
## Creating Known Issue Tests
1. Create the `ps1` file under `src\knownIssues` as the name of the validation test. e.g. `Test-SdnKIVfpDuplicatePort.ps1`
- Ensure that you prefix your function name as `Test-SdnKI`.
1. Function should return a PSCustomObject that contains the following format:
```
```powershell
# $issueIdentified should either be $true or $false depending on if issue was detected
# $properties will contain any related information in scenario of $true status
else {
@ -63,6 +78,11 @@ When creating a health validation test, ensure you:
- `Test-SdnKnownIssues` will automatically pick up tests under the `src\knownIssues` directory.
1. The infrastructure information can be retrieved from global cache at `$Global:SdnDiagnostics`
To help ensure consistency, leverage `.build\utilities\create-knownissue-function.ps1` to help create your functions. This will create a `.ps1` file off the specified template and place into the appropriate module under `src\knownIssues`. Example:
```powershell
.\create-knownissue-function.ps1 -FunctionName 'Test-SdnKIVfpDuplicatePort' -Template basic_knownIssue_template.ps1
```
# Build Validation and Testing
1. To generate a local build of the module, run `.\.build\build.ps1` which will generate an SdnDiagnostics module package to `~\out\build\SdnDiagnostics`.
1. Copy the module to `C:\Program Files\WindowsPowerShell\Modules`.
@ -70,12 +90,13 @@ When creating a health validation test, ensure you:
1. Install the modules to the SDN nodes in the dataplane.
```powershell
$uri = 'https://NcURI'
$netController = 'NC ComputerName'
$nodes = @()
$nodes += (Get-SdnServer -NcUri $uri -ManagementAddress)
$nodes += (Get-SdnGateway -NcUri $uri -ManagementAddress)
$nodes += (Get-SdnLoadBalancerMux -NcUri $uri -ManagementAddress)
$nodes += (Get-SdnNetworkController -NetworkController 'SA20N26-NC01' -ServerNameOnly)
$nodes += (Get-SdnNetworkController -NetworkController $netController -ServerNameOnly)
Install-SdnDiagnostic -ComputerName $nodes -Force
```