This commit is contained in:
Ben Claussen 2018-05-14 16:46:12 -04:00
parent cadaf4ab9b
commit be25833f5a
14 changed files with 790 additions and 469 deletions

2
.gitignore vendored
View file

@ -7,4 +7,4 @@
*.Package.ps1
CustomMenu.inf
Test-Module.ps1
Staging/*
Staging/

View file

@ -89,17 +89,17 @@ function BuildNewURI {
}
if ($HTTPS) {
Write-Verbose "Setting scheme to HTTPS"
Write-Verbose " Setting scheme to HTTPS"
$Scheme = 'https'
} else {
Write-Warning "Connecting via non-secure HTTP is not-recommended"
Write-Warning " Connecting via non-secure HTTP is not-recommended"
Write-Verbose "Setting scheme to HTTP"
Write-Verbose " Setting scheme to HTTP"
$Scheme = 'http'
if (-not $PSBoundParameters.ContainsKey('Port')) {
# Set the port to 80 if the user did not supply it
Write-Verbose "Setting port to 80 as default because it was not supplied by the user"
Write-Verbose " Setting port to 80 as default because it was not supplied by the user"
$Port = 80
}
}
@ -110,25 +110,142 @@ function BuildNewURI {
# Generate the path by trimming excess slashes and whitespace from the $segments[] and joining together
$uriBuilder.Path = "api/{0}/" -f ($Segments.ForEach({$_.trim('/').trim()}) -join '/')
Write-Verbose "URIPath: $($uriBuilder.Path)"
Write-Verbose " URIPath: $($uriBuilder.Path)"
if ($parameters) {
# Loop through the parameters and use the HttpUtility to create a Query string
[System.Collections.Specialized.NameValueCollection]$URIParams = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
foreach ($param in $Parameters.GetEnumerator()) {
Write-Verbose "Adding URI parameter $($param.Key):$($param.Value)"
Write-Verbose " Adding URI parameter $($param.Key):$($param.Value)"
$URIParams[$param.Key] = $param.Value
}
$uriBuilder.Query = $URIParams.ToString()
}
Write-Verbose "Completed building URIBuilder"
Write-Verbose " Completed building URIBuilder"
# Return the entire UriBuilder object
$uriBuilder
}
function BuildURIComponents {
[CmdletBinding()]
[OutputType([hashtable])]
param
(
[Parameter(Mandatory = $true)]
[System.Collections.ArrayList]$URISegments,
[Parameter(Mandatory = $true)]
[object]$ParametersDictionary,
[string[]]$SkipParameterByName
)
Write-Verbose "Building URI components"
$URIParameters = [System.Collections.Hashtable]::new()
foreach ($CmdletParameterName in $ParametersDictionary.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -in $SkipParameterByName) {
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($ParametersDictionary[$CmdletParameterName]).Count -gt 1) {
Write-Verbose " Joining IDs for parameter"
$URIParameters['id__in'] = $Id -join ','
} else {
Write-Verbose " Adding ID to segments"
[void]$uriSegments.Add($ParametersDictionary[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
Write-Verbose " Adding query parameter"
$URIParameters['q'] = $ParametersDictionary[$CmdletParameterName]
} else {
Write-Verbose " Adding $($CmdletParameterName.ToLower()) parameter"
$URIParameters[$CmdletParameterName.ToLower()] = $ParametersDictionary[$CmdletParameterName]
}
}
return @{
'Segments' = [System.Collections.ArrayList]$URISegments
'Parameters' = $URIParameters
}
}
function GetChoiceValidValues {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]$MajorObject,
[Parameter(Mandatory = $true)]
[object]$Choice
)
$ValidValues = New-Object System.Collections.ArrayList
if (-not $script:NetboxConfig.Choices.$MajorObject.$Choice) {
throw "Missing choices for $Choice"
}
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.$MajorObject.$Choice.value)
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.$MajorObject.$Choice.label)
if ($ValidValues.Count -eq 0) {
throw "Missing valid values for $MajorObject.$Choice"
}
return [System.Collections.ArrayList]$ValidValues
}
function ValidateChoice {
[CmdletBinding()]
[OutputType([uint16])]
param
(
[Parameter(Mandatory = $true)]
[ValidateSet('Circuits', 'Extras', 'IPAM', 'Virtualization', IgnoreCase = $true)]
[string]$MajorObject,
[Parameter(Mandatory = $true)]
[string]$ChoiceName
)
$ValidValues = GetChoiceValidValues -MajorObject $MajorObject -Choice $ChoiceName
Write-Verbose "Validating $ChoiceName"
Write-Verbose "Checking '$ProvidedValue' against $($ValidValues -join ', ')"
if ($ValidValues -inotcontains $ProvidedValue) {
throw "Invalid value '$ProvidedValue' for '$ChoiceName'. Must be one of: $($ValidValues -join ', ')"
}
# Convert the ProvidedValue to the integer value
try {
$intVal = [uint16]"$ProvidedValue"
} catch {
# It must not be a number, get the value from the label
$intVal = [uint16]$script:NetboxConfig.Choices.$MajorObject.$ChoiceName.Where({
$_.Label -eq $ProvidedValue
}).Value
}
return $intVal
}
function GetNetboxAPIErrorBody {
param
(
@ -233,9 +350,14 @@ function InvokeNetboxRequest {
Write-Verbose "Did NOT find results property on data, returning raw result"
return $result
}
}
}
}
#region Troubleshooting commands
function ThrowNetboxRESTError {
$uriSegments = [System.Collections.ArrayList]::new(@('fake', 'url'))
@ -246,8 +368,33 @@ function ThrowNetboxRESTError {
InvokeNetboxRequest -URI $uri -Raw
}
function CreateEnum {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]$EnumName,
[Parameter(Mandatory = $true)]
[pscustomobject]$Values,
[switch]$PassThru
)
$definition = @"
public enum $EnumName
{`n$(foreach ($value in $values) {"`t$($value.label) = $($value.value),`n"})
}
"@
if (-not ([System.Management.Automation.PSTypeName]"$EnumName").Type) {
#Write-Host $definition -ForegroundColor Green
Add-Type -TypeDefinition $definition -PassThru:$PassThru
} else {
Write-Warning "EnumType $EnumName already exists."
}
}
#endregion Troubleshooting commands

View file

@ -28,7 +28,7 @@ function VerifyIPAMChoices {
Internal function to verify provided values for static choices
.DESCRIPTION
When users connect to the API, choices for each major object are cached to the config variable.
When users connect to the API, choices for each major object are cached to the config variable.
These values are then utilized to verify if the provided value from a user is valid.
.PARAMETER ProvidedValue
@ -63,16 +63,20 @@ function VerifyIPAMChoices {
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'Loopback' -IPAddressFamily
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
.OUTPUTS
This function returns the integer value if valid. Otherwise, it will throw an error.
.NOTES
Additional information about the function.
.FUNCTIONALITY
This cmdlet is intended to be used internally and not exposed to the user
.OUTPUT
This function returns nothing if the value is valid. Otherwise, it will throw an error.
#>
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'service:protocol')]
[OutputType([uint16])]
param
(
[Parameter(Mandatory = $true)]
@ -111,32 +115,7 @@ function VerifyIPAMChoices {
[switch]$ServiceProtocol
)
$ValidValues = New-Object System.Collections.ArrayList
if (-not $script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName)) {
throw "Missing choices for $($PSCmdlet.ParameterSetName)"
}
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).value)
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).label)
if ($ValidValues.Count -eq 0) {
throw "Missing valid values for $($PSCmdlet.ParameterSetName)"
}
if ($ValidValues -inotcontains $ProvidedValue) {
throw "Invalid value '$ProvidedValue' for '$($PSCmdlet.ParameterSetName)'. Must be one of: $($ValidValues -join ', ')"
}
# Convert the ProvidedValue to the integer value
try {
$intVal = [uint16]"$ProvidedValue"
} catch {
# It must not be a number, get the value from the label
$intVal = [uint16]$script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).Where({$_.Label -eq $ProvidedValue}).Value
}
return $intVal
ValidateChoice -MajorObject 'IPAM' -ChoiceName $PSCmdlet.ParameterSetName
}
@ -148,7 +127,8 @@ function Get-NetboxIPAMAggregate {
[uint16]$Offset,
[string]$Family,
[ValidateNotNullOrEmpty()]
[object]$Family,
[datetime]$Date_Added,
@ -163,32 +143,15 @@ function Get-NetboxIPAMAggregate {
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates'))
$URIParameters = @{}
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -AggregateFamily
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates'))
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -236,44 +199,23 @@ function Get-NetboxIPAMAddress {
[switch]$Raw
)
if ($Family) {
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily
}
if ($Status) {
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus
}
if ($Role) {
if ($Role -ne $null) {
$PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole
}
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$URIParameters = @{}
$URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -309,21 +251,17 @@ function Get-NetboxIPAMAvailableIP {
[Parameter(Mandatory = $true)]
[uint16]$Prefix_ID,
[Alias('Limit')]
[uint16]$NumberOfIPs,
[Alias('NumberOfIPs')]
[uint16]$Limit,
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips'))
$uriParameters = @{}
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id'
if ($NumberOfIPs) {
[void]$uriParameters.Add('limit', $NumberOfIPs)
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $uriParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -458,45 +396,65 @@ function Get-NetboxIPAMPrefix {
[switch]$Raw
)
if ($Family) {
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -PrefixFamily
}
if ($Status) {
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -PrefixStatus
}
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes'))
$Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes'))
$URIParameters = @{
}
$URIComponents = BuildURIComponents -ParametersDictionary $PSBoundParameters -URISegments $Segments
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
function Add-NetboxIPAMAddress {
[CmdletBinding(DefaultParameterSetName = 'CIDR')]
[OutputType([pscustomobject])]
param
(
[Parameter(Mandatory = $true)]
[string]$Address,
[object]$Status = 'Active',
[uint16]$Tenant,
[uint16]$VRF,
[object]$Role,
[uint16]$NAT_Inside,
[hashtable]$Custom_Fields,
[uint16]$Interface,
[string]$Description,
[switch]$Raw
)
$segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus
if ($Role) {
$PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole
}
$URIComponents = BuildURIComponents -URISegments $segments -ParametersDictionary $PSBoundParameters
$URI = BuildNewURI -Segments $URIComponents.Segments
InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters -Raw:$Raw
}
@ -508,8 +466,3 @@ function Get-NetboxIPAMPrefix {

View file

@ -24,15 +24,7 @@ function SetupNetboxConfigVariable {
Write-Verbose "Creating NetboxConfig hashtable"
$script:NetboxConfig = @{
'Connected' = $false
'Choices' = @{
'Circuits' = $null
'DCIM' = $null
'Extras' = $null
'IPAM' = $null
'Secrets' = $null
'Tenancy' = $null
'Virtualization' = $null
}
'Choices' = @{}
}
}
@ -183,14 +175,16 @@ function Connect-NetboxAPI {
}
}
Write-Verbose "Caching static choices"
$script:NetboxConfig.Choices.Circuits = Get-NetboxCircuitsChoices
#$script:NetboxConfig.Choices.DCIM = Get-NetboxDCIMChoices
#$script:NetboxConfig.Choices.DCIM = Get-NetboxDCIMChoices # Not completed yet
$script:NetboxConfig.Choices.Extras = Get-NetboxExtrasChoices
$script:NetboxConfig.Choices.IPAM = Get-NetboxIPAMChoices
#$script:NetboxConfig.Choices.Secrets = Get-NetboxSecretsChoices
#$script:NetboxConfig.Choices.Tenancy = Get-NetboxTenancyChoices
#$script:NetboxConfig.Choices.Secrets = Get-NetboxSecretsChoices # Not completed yet
#$script:NetboxConfig.Choices.Tenancy = Get-NetboxTenancyChoices # Not completed yet
$script:NetboxConfig.Choices.Virtualization = Get-NetboxVirtualizationChoices
Write-Verbose "Connection process completed"
}
@ -201,4 +195,3 @@ function Connect-NetboxAPI {

View file

@ -11,6 +11,70 @@
Virtualization object functions
#>
function VerifyVirtualizationChoices {
<#
.SYNOPSIS
Internal function to verify provided values for static choices
.DESCRIPTION
When users connect to the API, choices for each major object are cached to the config variable.
These values are then utilized to verify if the provided value from a user is valid.
.PARAMETER ProvidedValue
The value to validate against static choices
.PARAMETER AggregateFamily
Verify against aggregate family values
.PARAMETER PrefixFamily
Verify against prefix family values
.PARAMETER PrefixStatus
Verify against prefix status values
.PARAMETER IPAddressFamily
Verify against ip-address family values
.PARAMETER IPAddressStatus
Verify against ip-address status values
.PARAMETER IPAddressRole
Verify against ip-address role values
.PARAMETER VLANStatus
Verify against VLAN status values
.PARAMETER ServiceProtocol
Verify against service protocol values
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'loopback' -IPAddressRole
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'Loopback' -IPAddressFamily
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
.FUNCTIONALITY
This cmdlet is intended to be used internally and not exposed to the user
.OUTPUT
This function returns nothing if the value is valid. Otherwise, it will throw an error.
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[object]$ProvidedValue,
[Parameter(ParameterSetName = 'virtual-machine:status',
Mandatory = $true)]
[switch]$VirtualMachineStatus
)
ValidateChoice -MajorObject 'Virtualization' -ChoiceName $PSCmdlet.ParameterSetName
}
#region GET commands
function Get-NetboxVirtualizationChoices {
@ -123,7 +187,7 @@ function Get-NetboxVirtualMachine {
[Alias('id__in')]
[uint16[]]$Id,
[NetboxVirtualMachineStatus]$Status,
[object]$Status,
[string]$Tenant,
@ -154,34 +218,15 @@ function Get-NetboxVirtualMachine {
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$URIParameters = @{}
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} elseif ($CmdletParameterName -eq 'Status') {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].value__
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -457,7 +502,7 @@ function Add-NetboxVirtualMachine {
[uint16]$Tenant,
[NetboxVirtualMachineStatus]$Status = 'Active',
[object]$Status = 'Active',
[uint16]$Role,
@ -474,31 +519,17 @@ function Add-NetboxVirtualMachine {
[string]$Comments
)
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus
}
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$Body = @{}
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
if (-not $PSBoundParameters.ContainsKey('Status')) {
[void]$PSBoundParameters.Add('Status', $Status)
}
$uri = BuildNewURI -Segments $URIComponents.Segments
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Status') {
$Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].value__
} else {
$Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments
InvokeNetboxRequest -URI $uri -Method POST -Body $Body
InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters
}
function Add-NetboxVirtualInterface {

View file

@ -6,16 +6,16 @@ $script:CommonParameterNames = New-Object System.Collections.ArrayList
SetupNetboxConfigVariable
if (-not ([System.Management.Automation.PSTypeName]'NetboxVirtualMachineStatus').Type) {
Add-Type -TypeDefinition @"
public enum NetboxVirtualMachineStatus
{
Offline = 0,
Active = 1,
Staged = 3
}
"@
}
#if (-not ([System.Management.Automation.PSTypeName]'NetboxVirtualMachineStatus').Type) {
# Add-Type -TypeDefinition @"
#public enum NetboxVirtualMachineStatus
#{
# Offline = 0,
# Active = 1,
# Staged = 3
#}
#"@
#}
Export-ModuleMember -Function *

View file

@ -26,6 +26,7 @@
<File Build="2" Shared="True" ReferenceFunction="Invoke-Virtualization_Tests_ps1">Tests\Virtualization.Tests.ps1</File>
<File Build="2" Shared="True" ReferenceFunction="Invoke-IPAM_Tests_ps1">Tests\IPAM.Tests.ps1</File>
<File Build="0" Shared="True" ReferenceFunction="Invoke-IPAM_ps1">Functions\IPAM\IPAM.ps1</File>
<File Build="2">Tests\IPAMChoices.json.txt</File>
</Files>
<StartupScript>R:\Netbox\NetboxPS\Test-Module.ps1</StartupScript>
</Project>

View file

@ -47,6 +47,8 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
}
InModuleScope -ModuleName 'NetboxPS' -ScriptBlock {
$script:NetboxConfig.Choices.IPAM = (Get-Content "$PSScriptRoot\IPAMChoices.json" -ErrorAction Stop | ConvertFrom-Json)
Context -Name "Get-NetboxIPAMAggregate" -Fixture {
It "Should request the default number of aggregates" {
$Result = Get-NetboxIPAMAggregate
@ -182,31 +184,25 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
#region TODO: Figure out how to mock/test Verification appropriately...
<#
It "Should request with a family number" {
Mock -CommandName 'Get-NetboxIPAMChoices' -ModuleName 'NetboxPS' -MockWith {
return @"
{"aggregate:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:status":[{"label":"Container","value":0},{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"ip-address:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"ip-address:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3},{"label":"DHCP","value":5}],"ip-address:role":[{"label":"Loopback","value":10},{"label":"Secondary","value":20},{"label":"Anycast","value":30},{"label":"VIP","value":40},{"label":"VRRP","value":41},{"label":"HSRP","value":42},{"label":"GLBP","value":43},{"label":"CARP","value":44}],"vlan:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"service:protocol":[{"label":"TCP","value":6},{"label":"UDP","value":17}]}
"@ | ConvertFrom-Json
}
Mock -CommandName 'Connect-NetboxAPI' -ModuleName 'NetboxPS' -MockWith {
$script:NetboxConfig.Connected = $true
$script:NetboxConfig.Choices.IPAM = Get-NetboxIPAMChoices
}
Connect-NetboxAPI
$Result = Get-NetboxIPAMAddress -Role 4
$Result = Get-NetboxIPAMAddress -Family 4
Assert-VerifiableMock
Assert-MockCalled -CommandName "Get-NetboxIPAMChoices"
$Result.Method | Should -Be 'GET'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?role=4'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?family=4'
$Result.Headers.Keys.Count | Should -BeExactly 1
}
It "Should request with a family name" {
$Result = Get-NetboxIPAMAddress -Family 'IPv4'
Assert-VerifiableMock
$Result.Method | Should -Be 'GET'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?family=4'
$Result.Headers.Keys.Count | Should -BeExactly 1
}
#>
#endregion
}
Context -Name "Get-NetboxIPAMAvailableIP" -Fixture {
@ -233,7 +229,7 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
}
}
Context -Name "Get-NetboxIPAMPrefix" {
Context -Name "Get-NetboxIPAMPrefix" -Fixture {
It "Should request the default number of prefixes" {
$Result = Get-NetboxIPAMPrefix
@ -311,11 +307,7 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
<#
It "Should request with family of 4" {
Mock -CommandName "VerifyIPAMChoices" -ModuleName 'NetboxPS' -MockWith {
return 4
} -Verifiable
$Result = Get-NetboxIPAMPrefix -Family 4
Assert-VerifiableMock
@ -325,7 +317,6 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
#>
It "Should throw because the mask length is too large" {
{
@ -356,6 +347,41 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
}
Context -Name "Add-NetboxIPAMAddress" -Fixture {
It "Should add a basic IP address" {
$Result = Add-NetboxIPAMAddress -Address '10.0.0.1/24'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":1,"address":"10.0.0.1/24"}'
}
It "Should add an IP with a status and role names" {
$Result = Add-NetboxIPAMAddress -Address '10.0.0.1/24' -Status 'Reserved' -Role 'Anycast'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":2,"role":30,"address":"10.0.0.1/24"}'
}
It "Should add an IP with a status and role values" {
$Result = Add-NetboxIPAMAddress -Address '10.0.1.1/24' -Status '1' -Role '10'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":1,"role":10,"address":"10.0.1.1/24"}'
}
}
}
}

1
Tests/IPAMChoices.json Normal file
View file

@ -0,0 +1 @@
{"aggregate:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:status":[{"label":"Container","value":0},{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"ip-address:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"ip-address:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3},{"label":"DHCP","value":5}],"ip-address:role":[{"label":"Loopback","value":10},{"label":"Secondary","value":20},{"label":"Anycast","value":30},{"label":"VIP","value":40},{"label":"VRRP","value":41},{"label":"HSRP","value":42},{"label":"GLBP","value":43},{"label":"CARP","value":44}],"vlan:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"service:protocol":[{"label":"TCP","value":6},{"label":"UDP","value":17}]}

View file

@ -46,6 +46,8 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
}
InModuleScope -ModuleName 'NetboxPS' -ScriptBlock {
$script:NetboxConfig.Choices.Virtualization = (Get-Content "$PSScriptRoot\VirtualizationChoices.json" -ErrorAction Stop | ConvertFrom-Json)
Context -Name "Get-NetboxVirtualMachine" -Fixture {
It "Should request the default number of VMs" {
$Result = Get-NetboxVirtualMachine
@ -305,6 +307,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
}
Context -Name "Add-NetboxVirtualMachine" -Fixture {
It "Should add a basic VM" {
$Result = Add-NetboxVirtualMachine -Name 'testvm' -Cluster 1
@ -313,7 +316,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/virtual-machines/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"cluster":1,"name":"testvm","status":1}'
$Result.Body | Should -Be '{"name":"testvm","cluster":1,"status":1}'
}
It "Should add a VM with CPUs, Memory, Disk, tenancy, and comments" {
@ -324,7 +327,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/virtual-machines/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"tenant":11,"comments":"these are comments","disk":50,"memory":4096,"name":"testvm","cluster":1,"status":1,"vcpus":4}'
$Result.Body | Should -Be '{"tenant":11,"name":"testvm","comments":"these are comments","cluster":1,"status":1,"memory":4096,"vcpus":4,"disk":50}'
}
}

View file

@ -0,0 +1 @@
{"virtual-machine:status":[{"label":"Active","value":1},{"label":"Offline","value":0},{"label":"Staged","value":3}]}

536
dist/NetboxPS.psm1 vendored
View file

@ -1,8 +1,8 @@
<#
.NOTES
--------------------------------------------------------------------------------
Code generated by: SAPIEN Technologies, Inc., PowerShell Studio 2018 v5.5.150
Generated on: 5/11/2018 4:30 PM
Code generated by: SAPIEN Technologies, Inc., PowerShell Studio 2018 v5.5.152
Generated on: 5/14/2018 4:35 PM
Generated by: Ben Claussen
Organization: NEOnet
--------------------------------------------------------------------------------
@ -103,17 +103,17 @@
}
if ($HTTPS) {
Write-Verbose "Setting scheme to HTTPS"
Write-Verbose " Setting scheme to HTTPS"
$Scheme = 'https'
} else {
Write-Warning "Connecting via non-secure HTTP is not-recommended"
Write-Warning " Connecting via non-secure HTTP is not-recommended"
Write-Verbose "Setting scheme to HTTP"
Write-Verbose " Setting scheme to HTTP"
$Scheme = 'http'
if (-not $PSBoundParameters.ContainsKey('Port')) {
# Set the port to 80 if the user did not supply it
Write-Verbose "Setting port to 80 as default because it was not supplied by the user"
Write-Verbose " Setting port to 80 as default because it was not supplied by the user"
$Port = 80
}
}
@ -124,25 +124,142 @@
# Generate the path by trimming excess slashes and whitespace from the $segments[] and joining together
$uriBuilder.Path = "api/{0}/" -f ($Segments.ForEach({$_.trim('/').trim()}) -join '/')
Write-Verbose "URIPath: $($uriBuilder.Path)"
Write-Verbose " URIPath: $($uriBuilder.Path)"
if ($parameters) {
# Loop through the parameters and use the HttpUtility to create a Query string
[System.Collections.Specialized.NameValueCollection]$URIParams = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
foreach ($param in $Parameters.GetEnumerator()) {
Write-Verbose "Adding URI parameter $($param.Key):$($param.Value)"
Write-Verbose " Adding URI parameter $($param.Key):$($param.Value)"
$URIParams[$param.Key] = $param.Value
}
$uriBuilder.Query = $URIParams.ToString()
}
Write-Verbose "Completed building URIBuilder"
Write-Verbose " Completed building URIBuilder"
# Return the entire UriBuilder object
$uriBuilder
}
function BuildURIComponents {
[CmdletBinding()]
[OutputType([hashtable])]
param
(
[Parameter(Mandatory = $true)]
[System.Collections.ArrayList]$URISegments,
[Parameter(Mandatory = $true)]
[object]$ParametersDictionary,
[string[]]$SkipParameterByName
)
Write-Verbose "Building URI components"
$URIParameters = [System.Collections.Hashtable]::new()
foreach ($CmdletParameterName in $ParametersDictionary.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -in $SkipParameterByName) {
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($ParametersDictionary[$CmdletParameterName]).Count -gt 1) {
Write-Verbose " Joining IDs for parameter"
$URIParameters['id__in'] = $Id -join ','
} else {
Write-Verbose " Adding ID to segments"
[void]$uriSegments.Add($ParametersDictionary[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
Write-Verbose " Adding query parameter"
$URIParameters['q'] = $ParametersDictionary[$CmdletParameterName]
} else {
Write-Verbose " Adding $($CmdletParameterName.ToLower()) parameter"
$URIParameters[$CmdletParameterName.ToLower()] = $ParametersDictionary[$CmdletParameterName]
}
}
return @{
'Segments' = [System.Collections.ArrayList]$URISegments
'Parameters' = $URIParameters
}
}
function GetChoiceValidValues {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]$MajorObject,
[Parameter(Mandatory = $true)]
[object]$Choice
)
$ValidValues = New-Object System.Collections.ArrayList
if (-not $script:NetboxConfig.Choices.$MajorObject.$Choice) {
throw "Missing choices for $Choice"
}
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.$MajorObject.$Choice.value)
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.$MajorObject.$Choice.label)
if ($ValidValues.Count -eq 0) {
throw "Missing valid values for $MajorObject.$Choice"
}
return [System.Collections.ArrayList]$ValidValues
}
function ValidateChoice {
[CmdletBinding()]
[OutputType([uint16])]
param
(
[Parameter(Mandatory = $true)]
[ValidateSet('Circuits', 'Extras', 'IPAM', 'Virtualization', IgnoreCase = $true)]
[string]$MajorObject,
[Parameter(Mandatory = $true)]
[string]$ChoiceName
)
$ValidValues = GetChoiceValidValues -MajorObject $MajorObject -Choice $ChoiceName
Write-Verbose "Validating $ChoiceName"
Write-Verbose "Checking '$ProvidedValue' against $($ValidValues -join ', ')"
if ($ValidValues -inotcontains $ProvidedValue) {
throw "Invalid value '$ProvidedValue' for '$ChoiceName'. Must be one of: $($ValidValues -join ', ')"
}
# Convert the ProvidedValue to the integer value
try {
$intVal = [uint16]"$ProvidedValue"
} catch {
# It must not be a number, get the value from the label
$intVal = [uint16]$script:NetboxConfig.Choices.$MajorObject.$ChoiceName.Where({
$_.Label -eq $ProvidedValue
}).Value
}
return $intVal
}
function GetNetboxAPIErrorBody {
param
(
@ -247,9 +364,14 @@
Write-Verbose "Did NOT find results property on data, returning raw result"
return $result
}
}
}
}
#region Troubleshooting commands
function ThrowNetboxRESTError {
$uriSegments = [System.Collections.ArrayList]::new(@('fake', 'url'))
@ -260,8 +382,33 @@
InvokeNetboxRequest -URI $uri -Raw
}
function CreateEnum {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[string]$EnumName,
[Parameter(Mandatory = $true)]
[pscustomobject]$Values,
[switch]$PassThru
)
$definition = @"
public enum $EnumName
{`n$(foreach ($value in $values) {"`t$($value.label) = $($value.value),`n"})
}
"@
if (-not ([System.Management.Automation.PSTypeName]"$EnumName").Type) {
#Write-Host $definition -ForegroundColor Green
Add-Type -TypeDefinition $definition -PassThru:$PassThru
} else {
Write-Warning "EnumType $EnumName already exists."
}
}
#endregion Troubleshooting commands
@ -297,15 +444,7 @@
Write-Verbose "Creating NetboxConfig hashtable"
$script:NetboxConfig = @{
'Connected' = $false
'Choices' = @{
'Circuits' = $null
'DCIM' = $null
'Extras' = $null
'IPAM' = $null
'Secrets' = $null
'Tenancy' = $null
'Virtualization' = $null
}
'Choices' = @{}
}
}
@ -456,14 +595,16 @@
}
}
Write-Verbose "Caching static choices"
$script:NetboxConfig.Choices.Circuits = Get-NetboxCircuitsChoices
#$script:NetboxConfig.Choices.DCIM = Get-NetboxDCIMChoices
#$script:NetboxConfig.Choices.DCIM = Get-NetboxDCIMChoices # Not completed yet
$script:NetboxConfig.Choices.Extras = Get-NetboxExtrasChoices
$script:NetboxConfig.Choices.IPAM = Get-NetboxIPAMChoices
#$script:NetboxConfig.Choices.Secrets = Get-NetboxSecretsChoices
#$script:NetboxConfig.Choices.Tenancy = Get-NetboxTenancyChoices
#$script:NetboxConfig.Choices.Secrets = Get-NetboxSecretsChoices # Not completed yet
#$script:NetboxConfig.Choices.Tenancy = Get-NetboxTenancyChoices # Not completed yet
$script:NetboxConfig.Choices.Virtualization = Get-NetboxVirtualizationChoices
Write-Verbose "Connection process completed"
}
@ -474,7 +615,6 @@
#endregion
#region Invoke-Extras_ps1
@ -626,6 +766,70 @@
Virtualization object functions
#>
function VerifyVirtualizationChoices {
<#
.SYNOPSIS
Internal function to verify provided values for static choices
.DESCRIPTION
When users connect to the API, choices for each major object are cached to the config variable.
These values are then utilized to verify if the provided value from a user is valid.
.PARAMETER ProvidedValue
The value to validate against static choices
.PARAMETER AggregateFamily
Verify against aggregate family values
.PARAMETER PrefixFamily
Verify against prefix family values
.PARAMETER PrefixStatus
Verify against prefix status values
.PARAMETER IPAddressFamily
Verify against ip-address family values
.PARAMETER IPAddressStatus
Verify against ip-address status values
.PARAMETER IPAddressRole
Verify against ip-address role values
.PARAMETER VLANStatus
Verify against VLAN status values
.PARAMETER ServiceProtocol
Verify against service protocol values
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'loopback' -IPAddressRole
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'Loopback' -IPAddressFamily
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
.FUNCTIONALITY
This cmdlet is intended to be used internally and not exposed to the user
.OUTPUT
This function returns nothing if the value is valid. Otherwise, it will throw an error.
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[object]$ProvidedValue,
[Parameter(ParameterSetName = 'virtual-machine:status',
Mandatory = $true)]
[switch]$VirtualMachineStatus
)
ValidateChoice -MajorObject 'Virtualization' -ChoiceName $PSCmdlet.ParameterSetName
}
#region GET commands
function Get-NetboxVirtualizationChoices {
@ -738,7 +942,7 @@
[Alias('id__in')]
[uint16[]]$Id,
[NetboxVirtualMachineStatus]$Status,
[object]$Status,
[string]$Tenant,
@ -769,34 +973,15 @@
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$URIParameters = @{}
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} elseif ($CmdletParameterName -eq 'Status') {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].value__
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -1072,7 +1257,7 @@
[uint16]$Tenant,
[NetboxVirtualMachineStatus]$Status = 'Active',
[object]$Status = 'Active',
[uint16]$Role,
@ -1089,31 +1274,17 @@
[string]$Comments
)
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus
}
$uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines'))
$Body = @{}
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
if (-not $PSBoundParameters.ContainsKey('Status')) {
[void]$PSBoundParameters.Add('Status', $Status)
}
$uri = BuildNewURI -Segments $URIComponents.Segments
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Status') {
$Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].value__
} else {
$Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments
InvokeNetboxRequest -URI $uri -Method POST -Body $Body
InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters
}
function Add-NetboxVirtualInterface {
@ -1198,7 +1369,7 @@
Internal function to verify provided values for static choices
.DESCRIPTION
When users connect to the API, choices for each major object are cached to the config variable.
When users connect to the API, choices for each major object are cached to the config variable.
These values are then utilized to verify if the provided value from a user is valid.
.PARAMETER ProvidedValue
@ -1233,16 +1404,20 @@
.EXAMPLE
PS C:\> VerifyIPAMChoices -ProvidedValue 'Loopback' -IPAddressFamily
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
>> Invalid value Loopback for ip-address:family. Must be one of: 4, 6, IPv4, IPv6
.OUTPUTS
This function returns the integer value if valid. Otherwise, it will throw an error.
.NOTES
Additional information about the function.
.FUNCTIONALITY
This cmdlet is intended to be used internally and not exposed to the user
.OUTPUT
This function returns nothing if the value is valid. Otherwise, it will throw an error.
#>
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'service:protocol')]
[OutputType([uint16])]
param
(
[Parameter(Mandatory = $true)]
@ -1281,32 +1456,7 @@
[switch]$ServiceProtocol
)
$ValidValues = New-Object System.Collections.ArrayList
if (-not $script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName)) {
throw "Missing choices for $($PSCmdlet.ParameterSetName)"
}
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).value)
[void]$ValidValues.AddRange($script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).label)
if ($ValidValues.Count -eq 0) {
throw "Missing valid values for $($PSCmdlet.ParameterSetName)"
}
if ($ValidValues -inotcontains $ProvidedValue) {
throw "Invalid value '$ProvidedValue' for '$($PSCmdlet.ParameterSetName)'. Must be one of: $($ValidValues -join ', ')"
}
# Convert the ProvidedValue to the integer value
try {
$intVal = [uint16]"$ProvidedValue"
} catch {
# It must not be a number, get the value from the label
$intVal = [uint16]$script:NetboxConfig.Choices.IPAM.$($PSCmdlet.ParameterSetName).Where({$_.Label -eq $ProvidedValue}).Value
}
return $intVal
ValidateChoice -MajorObject 'IPAM' -ChoiceName $PSCmdlet.ParameterSetName
}
@ -1318,7 +1468,8 @@
[uint16]$Offset,
[string]$Family,
[ValidateNotNullOrEmpty()]
[object]$Family,
[datetime]$Date_Added,
@ -1333,32 +1484,15 @@
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates'))
$URIParameters = @{}
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -AggregateFamily
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates'))
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -1406,44 +1540,23 @@
[switch]$Raw
)
if ($Family) {
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily
}
if ($Status) {
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus
}
if ($Role) {
if ($Role -ne $null) {
$PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole
}
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$URIParameters = @{}
$URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -1479,21 +1592,17 @@
[Parameter(Mandatory = $true)]
[uint16]$Prefix_ID,
[Alias('Limit')]
[uint16]$NumberOfIPs,
[Alias('NumberOfIPs')]
[uint16]$Limit,
[switch]$Raw
)
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips'))
$uriParameters = @{}
$URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id'
if ($NumberOfIPs) {
[void]$uriParameters.Add('limit', $NumberOfIPs)
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $uriParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
@ -1628,49 +1737,64 @@
[switch]$Raw
)
if ($Family) {
if ($Family -ne $null) {
$PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -PrefixFamily
}
if ($Status) {
if ($Status -ne $null) {
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -PrefixStatus
}
$uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes'))
$Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes'))
$URIParameters = @{
}
$URIComponents = BuildURIComponents -ParametersDictionary $PSBoundParameters -URISegments $Segments
foreach ($CmdletParameterName in $PSBoundParameters.Keys) {
if ($CmdletParameterName -in $CommonParameterNames) {
# These are common parameters and should not be appended to the URI
Write-Debug "Skipping parameter $CmdletParameterName"
continue
}
if ($CmdletParameterName -eq 'Id') {
# Check if there is one or more values for Id and build a URI or query as appropriate
if (@($PSBoundParameters[$CmdletParameterName]).Count -gt 1) {
$URIParameters['id__in'] = $Id -join ','
} else {
[void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName])
}
} elseif ($CmdletParameterName -eq 'Query') {
$URIParameters['q'] = $PSBoundParameters[$CmdletParameterName]
} else {
$URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName]
}
}
$uri = BuildNewURI -Segments $uriSegments -Parameters $URIParameters
$uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters
InvokeNetboxRequest -URI $uri -Raw:$Raw
}
function Add-NetboxIPAMAddress {
[CmdletBinding(DefaultParameterSetName = 'CIDR')]
[OutputType([pscustomobject])]
param
(
[Parameter(Mandatory = $true)]
[string]$Address,
[object]$Status = 'Active',
[uint16]$Tenant,
[uint16]$VRF,
[object]$Role,
[uint16]$NAT_Inside,
[hashtable]$Custom_Fields,
[uint16]$Interface,
[string]$Description,
[switch]$Raw
)
$segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses'))
$PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus
if ($Role) {
$PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole
}
$URIComponents = BuildURIComponents -URISegments $segments -ParametersDictionary $PSBoundParameters
$URI = BuildNewURI -Segments $URIComponents.Segments
InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters -Raw:$Raw
}
@ -1693,16 +1817,16 @@ $script:CommonParameterNames = New-Object System.Collections.ArrayList
SetupNetboxConfigVariable
if (-not ([System.Management.Automation.PSTypeName]'NetboxVirtualMachineStatus').Type) {
Add-Type -TypeDefinition @"
public enum NetboxVirtualMachineStatus
{
Offline = 0,
Active = 1,
Staged = 3
}
"@
}
#if (-not ([System.Management.Automation.PSTypeName]'NetboxVirtualMachineStatus').Type) {
# Add-Type -TypeDefinition @"
#public enum NetboxVirtualMachineStatus
#{
# Offline = 0,
# Active = 1,
# Staged = 3
#}
#"@
#}
Export-ModuleMember -Function *

View file

@ -47,6 +47,8 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
}
InModuleScope -ModuleName 'NetboxPS' -ScriptBlock {
$script:NetboxConfig.Choices.IPAM = (Get-Content "$PSScriptRoot\IPAMChoices.json" -ErrorAction Stop | ConvertFrom-Json)
Context -Name "Get-NetboxIPAMAggregate" -Fixture {
It "Should request the default number of aggregates" {
$Result = Get-NetboxIPAMAggregate
@ -182,31 +184,25 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
#region TODO: Figure out how to mock/test Verification appropriately...
<#
It "Should request with a family number" {
Mock -CommandName 'Get-NetboxIPAMChoices' -ModuleName 'NetboxPS' -MockWith {
return @"
{"aggregate:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"prefix:status":[{"label":"Container","value":0},{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"ip-address:family":[{"label":"IPv4","value":4},{"label":"IPv6","value":6}],"ip-address:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3},{"label":"DHCP","value":5}],"ip-address:role":[{"label":"Loopback","value":10},{"label":"Secondary","value":20},{"label":"Anycast","value":30},{"label":"VIP","value":40},{"label":"VRRP","value":41},{"label":"HSRP","value":42},{"label":"GLBP","value":43},{"label":"CARP","value":44}],"vlan:status":[{"label":"Active","value":1},{"label":"Reserved","value":2},{"label":"Deprecated","value":3}],"service:protocol":[{"label":"TCP","value":6},{"label":"UDP","value":17}]}
"@ | ConvertFrom-Json
}
Mock -CommandName 'Connect-NetboxAPI' -ModuleName 'NetboxPS' -MockWith {
$script:NetboxConfig.Connected = $true
$script:NetboxConfig.Choices.IPAM = Get-NetboxIPAMChoices
}
Connect-NetboxAPI
$Result = Get-NetboxIPAMAddress -Role 4
$Result = Get-NetboxIPAMAddress -Family 4
Assert-VerifiableMock
Assert-MockCalled -CommandName "Get-NetboxIPAMChoices"
$Result.Method | Should -Be 'GET'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?role=4'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?family=4'
$Result.Headers.Keys.Count | Should -BeExactly 1
}
It "Should request with a family name" {
$Result = Get-NetboxIPAMAddress -Family 'IPv4'
Assert-VerifiableMock
$Result.Method | Should -Be 'GET'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/?family=4'
$Result.Headers.Keys.Count | Should -BeExactly 1
}
#>
#endregion
}
Context -Name "Get-NetboxIPAMAvailableIP" -Fixture {
@ -233,7 +229,7 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
}
}
Context -Name "Get-NetboxIPAMPrefix" {
Context -Name "Get-NetboxIPAMPrefix" -Fixture {
It "Should request the default number of prefixes" {
$Result = Get-NetboxIPAMPrefix
@ -311,11 +307,7 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
<#
It "Should request with family of 4" {
Mock -CommandName "VerifyIPAMChoices" -ModuleName 'NetboxPS' -MockWith {
return 4
} -Verifiable
$Result = Get-NetboxIPAMPrefix -Family 4
Assert-VerifiableMock
@ -325,7 +317,24 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
#>
It "Should throw because the mask length is too large" {
{
Get-NetboxIPAMPrefix -Mask_length 128
} | Should -Throw
}
It "Should throw because the mask length is too small" {
{
Get-NetboxIPAMPrefix -Mask_length -1
} | Should -Throw
}
It "Should not throw because the mask length is just right" {
{
Get-NetboxIPAMPrefix -Mask_length 24
} | Should -Not -Throw
}
It "Should request with mask length 24" {
$Result = Get-NetboxIPAMPrefix -Mask_length 24
@ -337,11 +346,40 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture {
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Headers.Authorization | Should -Be "Token faketoken"
}
}
Context -Name "Add-NetboxIPAMAddress" -Fixture {
It "Should add a basic IP address" {
$Result = Add-NetboxIPAMAddress -Address '10.0.0.1/24'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":1,"address":"10.0.0.1/24"}'
}
It "Should throw because the mask length is too large" {
{
Get-NetboxIPAMPrefix -Mask_length 128
} | Should -Throw
It "Should add an IP with a status and role names" {
$Result = Add-NetboxIPAMAddress -Address '10.0.0.1/24' -Status 'Reserved' -Role 'Anycast'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":2,"role":30,"address":"10.0.0.1/24"}'
}
It "Should add an IP with a status and role values" {
$Result = Add-NetboxIPAMAddress -Address '10.0.1.1/24' -Status '1' -Role '10'
Assert-VerifiableMock
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"status":1,"role":10,"address":"10.0.1.1/24"}'
}
}
}

View file

@ -46,6 +46,8 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
}
InModuleScope -ModuleName 'NetboxPS' -ScriptBlock {
$script:NetboxConfig.Choices.Virtualization = (Get-Content "$PSScriptRoot\VirtualizationChoices.json" -ErrorAction Stop | ConvertFrom-Json)
Context -Name "Get-NetboxVirtualMachine" -Fixture {
It "Should request the default number of VMs" {
$Result = Get-NetboxVirtualMachine
@ -305,6 +307,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
}
Context -Name "Add-NetboxVirtualMachine" -Fixture {
It "Should add a basic VM" {
$Result = Add-NetboxVirtualMachine -Name 'testvm' -Cluster 1
@ -313,7 +316,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/virtual-machines/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"cluster":1,"name":"testvm","status":1}'
$Result.Body | Should -Be '{"name":"testvm","cluster":1,"status":1}'
}
It "Should add a VM with CPUs, Memory, Disk, tenancy, and comments" {
@ -324,7 +327,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture {
$Result.Method | Should -Be 'POST'
$Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/virtual-machines/'
$Result.Headers.Keys.Count | Should -BeExactly 1
$Result.Body | Should -Be '{"tenant":11,"comments":"these are comments","disk":50,"memory":4096,"name":"testvm","cluster":1,"status":1,"vcpus":4}'
$Result.Body | Should -Be '{"tenant":11,"name":"testvm","comments":"these are comments","cluster":1,"status":1,"memory":4096,"vcpus":4,"disk":50}'
}
}