diff --git a/Functions/Helpers.ps1 b/Functions/Helpers.ps1 index 170bcb4..685fac7 100644 --- a/Functions/Helpers.ps1 +++ b/Functions/Helpers.ps1 @@ -340,7 +340,7 @@ function InvokeNetboxRequest { # If the user wants the raw value from the API... otherwise return only the actual result if ($Raw) { - Write-Verbose "Returning raw result" + Write-Verbose "Returning raw result by choice" return $result } else { if ($result.psobject.Properties.Name.Contains('results')) { diff --git a/Functions/IPAM/IPAM.ps1 b/Functions/IPAM/IPAM.ps1 index 7167c0a..0e42c2c 100644 --- a/Functions/IPAM/IPAM.ps1 +++ b/Functions/IPAM/IPAM.ps1 @@ -127,7 +127,6 @@ function Get-NetboxIPAMAggregate { [uint16]$Offset, - [ValidateNotNullOrEmpty()] [object]$Family, [datetime]$Date_Added, @@ -147,9 +146,9 @@ function Get-NetboxIPAMAggregate { $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -AggregateFamily } - $uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates')) + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -200,7 +199,7 @@ function Get-NetboxIPAMAddress { ) if ($Family -ne $null) { - $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily + $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily } if ($Status -ne $null) { @@ -257,9 +256,9 @@ function Get-NetboxIPAMAvailableIP { [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips')) + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id' + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id' $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -406,7 +405,7 @@ function Get-NetboxIPAMPrefix { $Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes')) - $URIComponents = BuildURIComponents -ParametersDictionary $PSBoundParameters -URISegments $Segments + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -414,7 +413,51 @@ function Get-NetboxIPAMPrefix { } function Add-NetboxIPAMAddress { - [CmdletBinding(DefaultParameterSetName = 'CIDR')] +<# + .SYNOPSIS + Add a new IP address to Netbox + + .DESCRIPTION + Adds a new IP address to Netbox with a status of Active by default. + + .PARAMETER Address + IP address in CIDR notation: 192.168.1.1/24 + + .PARAMETER Status + Status of the IP. Defaults to Active + + .PARAMETER Tenant + Tenant ID + + .PARAMETER VRF + VRF ID + + .PARAMETER Role + Role such as anycast, loopback, etc... Defaults to nothing + + .PARAMETER NAT_Inside + ID of IP for NAT + + .PARAMETER Custom_Fields + Custom field hash table. Will be validated by the API service + + .PARAMETER Interface + ID of interface to apply IP + + .PARAMETER Description + Description of IP address + + .PARAMETER Raw + Return raw results from API service + + .EXAMPLE + PS C:\> Add-NetboxIPAMAddress + + .NOTES + Additional information about the function. +#> + + [CmdletBinding()] [OutputType([pscustomobject])] param ( @@ -440,19 +483,118 @@ function Add-NetboxIPAMAddress { [switch]$Raw ) + $PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus + + if ($Role -ne $null) { + $PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole + } + $segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses')) + $URIComponents = BuildURIComponents -URISegments $segments -ParametersDictionary $PSBoundParameters + + $URI = BuildNewURI -Segments $URIComponents.Segments + + InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters -Raw:$Raw +} + +function Remove-NetboxIPAMAddress { +<# + .SYNOPSIS + Remove an IP address from Netbox + + .DESCRIPTION + Removes/deletes an IP address from Netbox by ID and optional other filters + + .PARAMETER Id + A description of the Id parameter. + + .PARAMETER Force + A description of the Force parameter. + + .PARAMETER Query + A description of the Query parameter. + + .EXAMPLE + PS C:\> Remove-NetboxIPAMAddress -Id $value1 + + .NOTES + Additional information about the function. +#> + + [CmdletBinding(ConfirmImpact = 'High', + SupportsShouldProcess = $true)] + param + ( + [Parameter(Mandatory = $true)] + [uint16[]]$Id, + + [switch]$Force + ) + + $CurrentIPs = @(Get-NetboxIPAMAddress -Id $Id -ErrorAction Stop) + + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses')) + + foreach ($IP in $CurrentIPs) { + if ($Force -or $pscmdlet.ShouldProcess($IP.Address, "Delete")) { + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary @{'id' = $IP.Id} + + $URI = BuildNewURI -Segments $URIComponents.Segments + + InvokeNetboxRequest -URI $URI -Method DELETE + } + } +} + +function Set-NetboxIPAMAddress { + [CmdletBinding(ConfirmImpact = 'High', + SupportsShouldProcess = $true)] + param + ( + [Parameter(Mandatory = $true, + ValueFromPipelineByPropertyName = $true)] + [uint16]$Id, + + [string]$Address, + + [object]$Status = 'Active', + + [uint16]$Tenant, + + [uint16]$VRF, + + [object]$Role, + + [uint16]$NAT_Inside, + + [hashtable]$Custom_Fields, + + [uint16]$Interface, + + [string]$Description, + + [switch]$Force + ) + $PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus if ($Role) { $PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole } + + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses', $Id)) + + Write-Verbose "Obtaining IPs from ID $Id" + $CurrentIP = Get-NetboxIPAMAddress -Id $Id -ErrorAction Stop + + if ($Force -or $PSCmdlet.ShouldProcess($($CurrentIP | Select-Object -ExpandProperty 'Address'), 'Set')) { + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary $PSBoundParameters -SkipParameterByName 'Id', 'Force' - $URIComponents = BuildURIComponents -URISegments $segments -ParametersDictionary $PSBoundParameters - - $URI = BuildNewURI -Segments $URIComponents.Segments - - InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters -Raw:$Raw + $URI = BuildNewURI -Segments $URIComponents.Segments + + InvokeNetboxRequest -URI $URI -Body $URIComponents.Parameters -Method PATCH + } } @@ -464,5 +606,3 @@ function Add-NetboxIPAMAddress { - - diff --git a/Functions/Virtualization/Virtualization.ps1 b/Functions/Virtualization/Virtualization.ps1 index 7906201..c4f27bd 100644 --- a/Functions/Virtualization/Virtualization.ps1 +++ b/Functions/Virtualization/Virtualization.ps1 @@ -83,7 +83,7 @@ function Get-NetboxVirtualizationChoices { $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', '_choices')) - $uri = BuildNewURI -Segments $uriSegments -Parameters $Parameters + $uri = BuildNewURI -Segments $uriSegments InvokeNetboxRequest -URI $uri } @@ -184,7 +184,6 @@ function Get-NetboxVirtualMachine { [string]$Name, - [Alias('id__in')] [uint16[]]$Id, [object]$Status, @@ -222,9 +221,9 @@ function Get-NetboxVirtualMachine { $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus } - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -279,61 +278,33 @@ function Get-NetboxVirtualMachineInterface { [CmdletBinding()] param ( - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [uint16]$Limit, - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [uint16]$Offset, [Parameter(ValueFromPipeline = $true)] [uint16]$Id, - [Parameter(ValueFromPipeline = $true)] [string]$Name, - [Parameter(ValueFromPipeline = $true)] [boolean]$Enabled, - [Parameter(ValueFromPipeline = $true)] [uint16]$MTU, - [Parameter(ValueFromPipeline = $true)] [uint16]$Virtual_Machine_Id, - [Parameter(ValueFromPipeline = $true)] [string]$Virtual_Machine, - [Parameter(ValueFromPipeline = $true)] [string]$MAC_Address, - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) - $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') { - [void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName]) - } elseif ($CmdletParameterName -eq 'Enabled') { - $URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].ToString().ToLower() - } 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 } @@ -519,17 +490,15 @@ function Add-NetboxVirtualMachine { [string]$Comments ) - if ($Status -ne $null) { - $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus - } + $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters - $uri = BuildNewURI -Segments $URIComponents.Segments + $URI = BuildNewURI -Segments $URIComponents.Segments - InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters + InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters } function Add-NetboxVirtualInterface { @@ -553,27 +522,15 @@ function Add-NetboxVirtualInterface { [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) - $Body = @{} + $PSBoundParameters.Enabled = $Enabled - if (-not $PSBoundParameters.ContainsKey('Enabled')) { - [void]$PSBoundParameters.Add('enabled', $Enabled) - } + $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 - } - - $Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName] - } + $uri = BuildNewURI -Segments $URIComponents.Segments - $uri = BuildNewURI -Segments $uriSegments - - InvokeNetboxRequest -URI $uri -Method POST -Body $Body + InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters } diff --git a/Tests/IPAM.Tests.ps1 b/Tests/IPAM.Tests.ps1 index fa76b77..6e6485b 100644 --- a/Tests/IPAM.Tests.ps1 +++ b/Tests/IPAM.Tests.ps1 @@ -382,6 +382,84 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture { $Result.Body | Should -Be '{"status":1,"role":10,"address":"10.0.1.1/24"}' } } + + Context -Name "Remove-NetboxIPAMAddress" -Fixture { + It "Should remove a single IP" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + } + } + + $Result = Remove-NetboxIPAMAddress -Id '4109' -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'DELETE' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be $null + } + + It "Should remove multiple IPs" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @( + @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + }, + @{ + 'address' = '10.1.1.2/24' + 'id' = 4110 + } + ) + } + + $Result = Remove-NetboxIPAMAddress -Id 4109, 4110 -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 2 + + $Result.Method | Should -Be 'DELETE', 'DELETE' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/', 'https://netbox.domain.com/api/ipam/ip-addresses/4110/' + $Result.Headers.Keys.Count | Should -BeExactly 2 + } + } + + Context -Name "Set-NetboxIPAMAddress" -Fixture { + It "Should set an IP with a new status" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + } + } + + $Result = Set-NetboxIPAMAddress -Id '4109' -Status 2 -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'PATCH' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be '{"status":2}' + } + + It "Should set an IP with VRF, Tenant, and Description" { + $Result = Set-NetboxIPAMAddress -Id 4109 -VRF 10 -Tenant 14 -Description 'Test description' -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'PATCH' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be '{"description":"Test description","status":1,"tenant":14,"vrf":10}' + } + } } } diff --git a/Tests/Virtualization.Tests.ps1 b/Tests/Virtualization.Tests.ps1 index 9d55c57..665b69a 100644 --- a/Tests/Virtualization.Tests.ps1 +++ b/Tests/Virtualization.Tests.ps1 @@ -130,7 +130,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineInterface" -Fixture { + Context -Name "Get-NetboxVirtualMachineInterface" -Fixture { It "Should request the default number of interfaces" { $Result = Get-NetboxVirtualMachineInterface @@ -192,7 +192,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineCluster" -Fixture { + Context -Name "Get-NetboxVirtualMachineCluster" -Fixture { It "Should request the default number of clusters" { $Result = Get-NetboxVirtualizationCluster @@ -264,7 +264,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineClusterGroup" -Fixture { + Context -Name "Get-NetboxVirtualMachineClusterGroup" -Fixture { It "Should request the default number of cluster groups" { $Result = Get-NetboxVirtualizationClusterGroup @@ -340,7 +340,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { $Result.Method | Should -Be 'POST' $Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/interfaces/' $Result.Headers.Keys.Count | Should -BeExactly 1 - $Result.Body | Should -Be '{"virtual_machine":10,"name":"Ethernet0","enabled":true}' + $Result.Body | Should -Be '{"virtual_machine":10,"enabled":true,"name":"Ethernet0"}' } It "Should add an interface with a MAC, MTU, and Description" { @@ -351,7 +351,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { $Result.Method | Should -Be 'POST' $Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/interfaces/' $Result.Headers.Keys.Count | Should -BeExactly 1 - $Result.Body | Should -Be '{"mtu":1500,"description":"Test description","enabled":true,"virtual_machine":10,"name":"Ethernet0","mac_address":"11:22:33:44:55:66"}' + $Result.Body | Should -Be '{"description":"Test description","virtual_machine":10,"enabled":true,"name":"Ethernet0","mtu":1500,"mac_address":"11:22:33:44:55:66"}' } } } diff --git a/dist/NetboxPS.psm1 b/dist/NetboxPS.psm1 index 1b85d37..105eddd 100644 --- a/dist/NetboxPS.psm1 +++ b/dist/NetboxPS.psm1 @@ -2,7 +2,7 @@ .NOTES -------------------------------------------------------------------------------- Code generated by: SAPIEN Technologies, Inc., PowerShell Studio 2018 v5.5.152 - Generated on: 5/14/2018 4:35 PM + Generated on: 5/15/2018 4:52 PM Generated by: Ben Claussen Organization: NEOnet -------------------------------------------------------------------------------- @@ -354,7 +354,7 @@ # If the user wants the raw value from the API... otherwise return only the actual result if ($Raw) { - Write-Verbose "Returning raw result" + Write-Verbose "Returning raw result by choice" return $result } else { if ($result.psobject.Properties.Name.Contains('results')) { @@ -838,7 +838,7 @@ public enum $EnumName $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', '_choices')) - $uri = BuildNewURI -Segments $uriSegments -Parameters $Parameters + $uri = BuildNewURI -Segments $uriSegments InvokeNetboxRequest -URI $uri } @@ -939,7 +939,6 @@ public enum $EnumName [string]$Name, - [Alias('id__in')] [uint16[]]$Id, [object]$Status, @@ -977,9 +976,9 @@ public enum $EnumName $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus } - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -1034,61 +1033,33 @@ public enum $EnumName [CmdletBinding()] param ( - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [uint16]$Limit, - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [uint16]$Offset, [Parameter(ValueFromPipeline = $true)] [uint16]$Id, - [Parameter(ValueFromPipeline = $true)] [string]$Name, - [Parameter(ValueFromPipeline = $true)] [boolean]$Enabled, - [Parameter(ValueFromPipeline = $true)] [uint16]$MTU, - [Parameter(ValueFromPipeline = $true)] [uint16]$Virtual_Machine_Id, - [Parameter(ValueFromPipeline = $true)] [string]$Virtual_Machine, - [Parameter(ValueFromPipeline = $true)] [string]$MAC_Address, - [Parameter(ValueFromPipeline = $true, - ValueFromPipelineByPropertyName = $true)] [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) - $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') { - [void]$uriSegments.Add($PSBoundParameters[$CmdletParameterName]) - } elseif ($CmdletParameterName -eq 'Enabled') { - $URIParameters[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName].ToString().ToLower() - } 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 } @@ -1274,17 +1245,15 @@ public enum $EnumName [string]$Comments ) - if ($Status -ne $null) { - $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus - } + $PSBoundParameters.Status = VerifyVirtualizationChoices -ProvidedValue $Status -VirtualMachineStatus - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'virtual-machines')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters - $uri = BuildNewURI -Segments $URIComponents.Segments + $URI = BuildNewURI -Segments $URIComponents.Segments - InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters + InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters } function Add-NetboxVirtualInterface { @@ -1308,27 +1277,15 @@ public enum $EnumName [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) + $Segments = [System.Collections.ArrayList]::new(@('virtualization', 'interfaces')) - $Body = @{} + $PSBoundParameters.Enabled = $Enabled - if (-not $PSBoundParameters.ContainsKey('Enabled')) { - [void]$PSBoundParameters.Add('enabled', $Enabled) - } + $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 - } - - $Body[$CmdletParameterName.ToLower()] = $PSBoundParameters[$CmdletParameterName] - } + $uri = BuildNewURI -Segments $URIComponents.Segments - $uri = BuildNewURI -Segments $uriSegments - - InvokeNetboxRequest -URI $uri -Method POST -Body $Body + InvokeNetboxRequest -URI $uri -Method POST -Body $URIComponents.Parameters } @@ -1468,7 +1425,6 @@ public enum $EnumName [uint16]$Offset, - [ValidateNotNullOrEmpty()] [object]$Family, [datetime]$Date_Added, @@ -1488,9 +1444,9 @@ public enum $EnumName $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -AggregateFamily } - $uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates')) + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'aggregates')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -1541,7 +1497,7 @@ public enum $EnumName ) if ($Family -ne $null) { - $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily + $PSBoundParameters.Family = VerifyIPAMChoices -ProvidedValue $Family -IPAddressFamily } if ($Status -ne $null) { @@ -1598,9 +1554,9 @@ public enum $EnumName [switch]$Raw ) - $uriSegments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips')) + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes', $Prefix_ID, 'available-ips')) - $URIComponents = BuildURIComponents -URISegments $uriSegments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id' + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters -SkipParameterByName 'prefix_id' $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -1747,7 +1703,7 @@ public enum $EnumName $Segments = [System.Collections.ArrayList]::new(@('ipam', 'prefixes')) - $URIComponents = BuildURIComponents -ParametersDictionary $PSBoundParameters -URISegments $Segments + $URIComponents = BuildURIComponents -URISegments $Segments -ParametersDictionary $PSBoundParameters $uri = BuildNewURI -Segments $URIComponents.Segments -Parameters $URIComponents.Parameters @@ -1755,7 +1711,51 @@ public enum $EnumName } function Add-NetboxIPAMAddress { - [CmdletBinding(DefaultParameterSetName = 'CIDR')] + <# + .SYNOPSIS + Add a new IP address to Netbox + + .DESCRIPTION + Adds a new IP address to Netbox with a status of Active by default. + + .PARAMETER Address + IP address in CIDR notation: 192.168.1.1/24 + + .PARAMETER Status + Status of the IP. Defaults to Active + + .PARAMETER Tenant + Tenant ID + + .PARAMETER VRF + VRF ID + + .PARAMETER Role + Role such as anycast, loopback, etc... Defaults to nothing + + .PARAMETER NAT_Inside + ID of IP for NAT + + .PARAMETER Custom_Fields + Custom field hash table. Will be validated by the API service + + .PARAMETER Interface + ID of interface to apply IP + + .PARAMETER Description + Description of IP address + + .PARAMETER Raw + Return raw results from API service + + .EXAMPLE + PS C:\> Add-NetboxIPAMAddress + + .NOTES + Additional information about the function. + #> + + [CmdletBinding()] [OutputType([pscustomobject])] param ( @@ -1781,14 +1781,14 @@ public enum $EnumName [switch]$Raw ) - $segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses')) - $PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus - if ($Role) { + if ($Role -ne $null) { $PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole } - + + $segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses')) + $URIComponents = BuildURIComponents -URISegments $segments -ParametersDictionary $PSBoundParameters $URI = BuildNewURI -Segments $URIComponents.Segments @@ -1796,7 +1796,104 @@ public enum $EnumName InvokeNetboxRequest -URI $URI -Method POST -Body $URIComponents.Parameters -Raw:$Raw } + function Remove-NetboxIPAMAddress { + <# + .SYNOPSIS + Remove an IP address from Netbox + + .DESCRIPTION + Removes/deletes an IP address from Netbox by ID and optional other filters + + .PARAMETER Id + A description of the Id parameter. + + .PARAMETER Force + A description of the Force parameter. + + .PARAMETER Query + A description of the Query parameter. + + .EXAMPLE + PS C:\> Remove-NetboxIPAMAddress -Id $value1 + + .NOTES + Additional information about the function. + #> + + [CmdletBinding(ConfirmImpact = 'High', + SupportsShouldProcess = $true)] + param + ( + [Parameter(Mandatory = $true)] + [uint16[]]$Id, + + [switch]$Force + ) + + $CurrentIPs = @(Get-NetboxIPAMAddress -Id $Id -ErrorAction Stop) + + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses')) + + foreach ($IP in $CurrentIPs) { + if ($Force -or $pscmdlet.ShouldProcess($IP.Address, "Delete")) { + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary @{'id' = $IP.Id} + + $URI = BuildNewURI -Segments $URIComponents.Segments + + InvokeNetboxRequest -URI $URI -Method DELETE + } + } + } + function Set-NetboxIPAMAddress { + [CmdletBinding(ConfirmImpact = 'High', + SupportsShouldProcess = $true)] + param + ( + [Parameter(Mandatory = $true, + ValueFromPipelineByPropertyName = $true)] + [uint16]$Id, + + [string]$Address, + + [object]$Status = 'Active', + + [uint16]$Tenant, + + [uint16]$VRF, + + [object]$Role, + + [uint16]$NAT_Inside, + + [hashtable]$Custom_Fields, + + [uint16]$Interface, + + [string]$Description, + + [switch]$Force + ) + + $PSBoundParameters.Status = VerifyIPAMChoices -ProvidedValue $Status -IPAddressStatus + + if ($Role) { + $PSBoundParameters.Role = VerifyIPAMChoices -ProvidedValue $Role -IPAddressRole + } + + $Segments = [System.Collections.ArrayList]::new(@('ipam', 'ip-addresses', $Id)) + + Write-Verbose "Obtaining IPs from ID $Id" + $CurrentIP = Get-NetboxIPAMAddress -Id $Id -ErrorAction Stop + + if ($Force -or $PSCmdlet.ShouldProcess($($CurrentIP | Select-Object -ExpandProperty 'Address'), 'Set')) { + $URIComponents = BuildURIComponents -URISegments $Segments.Clone() -ParametersDictionary $PSBoundParameters -SkipParameterByName 'Id', 'Force' + + $URI = BuildNewURI -Segments $URIComponents.Segments + + InvokeNetboxRequest -URI $URI -Body $URIComponents.Parameters -Method PATCH + } + } diff --git a/dist/Tests/IPAM.Tests.ps1 b/dist/Tests/IPAM.Tests.ps1 index fa76b77..6e6485b 100644 --- a/dist/Tests/IPAM.Tests.ps1 +++ b/dist/Tests/IPAM.Tests.ps1 @@ -382,6 +382,84 @@ Describe -Name "IPAM tests" -Tag 'Ipam' -Fixture { $Result.Body | Should -Be '{"status":1,"role":10,"address":"10.0.1.1/24"}' } } + + Context -Name "Remove-NetboxIPAMAddress" -Fixture { + It "Should remove a single IP" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + } + } + + $Result = Remove-NetboxIPAMAddress -Id '4109' -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'DELETE' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be $null + } + + It "Should remove multiple IPs" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @( + @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + }, + @{ + 'address' = '10.1.1.2/24' + 'id' = 4110 + } + ) + } + + $Result = Remove-NetboxIPAMAddress -Id 4109, 4110 -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 2 + + $Result.Method | Should -Be 'DELETE', 'DELETE' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/', 'https://netbox.domain.com/api/ipam/ip-addresses/4110/' + $Result.Headers.Keys.Count | Should -BeExactly 2 + } + } + + Context -Name "Set-NetboxIPAMAddress" -Fixture { + It "Should set an IP with a new status" { + Mock -CommandName "Get-NetboxIPAMAddress" -ModuleName NetboxPS -MockWith { + return @{ + 'address' = '10.1.1.1/24' + 'id' = 4109 + } + } + + $Result = Set-NetboxIPAMAddress -Id '4109' -Status 2 -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'PATCH' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be '{"status":2}' + } + + It "Should set an IP with VRF, Tenant, and Description" { + $Result = Set-NetboxIPAMAddress -Id 4109 -VRF 10 -Tenant 14 -Description 'Test description' -Force + + Assert-VerifiableMock + Assert-MockCalled -CommandName "Get-NetboxIPAMAddress" -Times 1 + + $Result.Method | Should -Be 'PATCH' + $Result.Uri | Should -Be 'https://netbox.domain.com/api/ipam/ip-addresses/4109/' + $Result.Headers.Keys.Count | Should -BeExactly 1 + $Result.Body | Should -Be '{"description":"Test description","status":1,"tenant":14,"vrf":10}' + } + } } } diff --git a/dist/Tests/Virtualization.Tests.ps1 b/dist/Tests/Virtualization.Tests.ps1 index 9d55c57..665b69a 100644 --- a/dist/Tests/Virtualization.Tests.ps1 +++ b/dist/Tests/Virtualization.Tests.ps1 @@ -130,7 +130,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineInterface" -Fixture { + Context -Name "Get-NetboxVirtualMachineInterface" -Fixture { It "Should request the default number of interfaces" { $Result = Get-NetboxVirtualMachineInterface @@ -192,7 +192,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineCluster" -Fixture { + Context -Name "Get-NetboxVirtualMachineCluster" -Fixture { It "Should request the default number of clusters" { $Result = Get-NetboxVirtualizationCluster @@ -264,7 +264,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { } } - Context -Name "Get-VirtualMachineClusterGroup" -Fixture { + Context -Name "Get-NetboxVirtualMachineClusterGroup" -Fixture { It "Should request the default number of cluster groups" { $Result = Get-NetboxVirtualizationClusterGroup @@ -340,7 +340,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { $Result.Method | Should -Be 'POST' $Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/interfaces/' $Result.Headers.Keys.Count | Should -BeExactly 1 - $Result.Body | Should -Be '{"virtual_machine":10,"name":"Ethernet0","enabled":true}' + $Result.Body | Should -Be '{"virtual_machine":10,"enabled":true,"name":"Ethernet0"}' } It "Should add an interface with a MAC, MTU, and Description" { @@ -351,7 +351,7 @@ Describe -Name "Virtualization tests" -Tag 'Virtualization' -Fixture { $Result.Method | Should -Be 'POST' $Result.Uri | Should -Be 'https://netbox.domain.com/api/virtualization/interfaces/' $Result.Headers.Keys.Count | Should -BeExactly 1 - $Result.Body | Should -Be '{"mtu":1500,"description":"Test description","enabled":true,"virtual_machine":10,"name":"Ethernet0","mac_address":"11:22:33:44:55:66"}' + $Result.Body | Should -Be '{"description":"Test description","virtual_machine":10,"enabled":true,"name":"Ethernet0","mtu":1500,"mac_address":"11:22:33:44:55:66"}' } } }