Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,33 +132,40 @@ jobs:
$topo2 | ConvertTo-Json -Depth 10 | Out-File -FilePath $currTopo -Encoding utf8
$diff = Compare-NetworkScans -BaselineMetadata $baselineMeta -BaselineTopology $baselineTopo -CurrentMetadata $currMeta -CurrentTopology $currTopo
Write-Host "Compare-NetworkScans OK: $($diff | ConvertTo-Json -Depth 5)"
# Dual-stack DrawIO: Import-Inventory is IPv4-only; persist via topology JSON.
$v6Path = Join-Path $tmp 'smoke-ipv6-topo.json'
@{
Nodes = @(
@{ IP = '2001:db8::10'; Hostname = 'v6-node'; Role = 'switch'; Vendor = 'Cisco'; OS = 'IOS'; Layer = 'Access'; Reachable = $null }
@{ IP = '10.0.0.1'; Hostname = 'gw'; Role = 'core-router'; Vendor = 'Cisco'; OS = 'IOS'; Layer = 'Core'; Reachable = $null }
# Dual-stack DrawIO via Import-Inventory (v4 + v6 node/subnet; no hand-built topology).
$dualInv = @{
knownDevices = @(
@{ ip='10.0.0.1'; hostname='gw'; role='core-router'; vendor='Cisco' }
@{ ip='2001:db8::10'; hostname='v6-node'; role='switch'; vendor='Cisco' }
)
Edges = @()
Subnets = @(
@{ CIDR = '2001:db8::/32'; Label = 'SmokeV6'; VLAN = 100 }
@{ CIDR = '10.0.0.0/24'; Label = 'SmokeNet'; VLAN = 1 }
subnets = @(
@{ cidr='10.0.0.0/24'; label='SmokeNet'; vlan=1 }
@{ cidr='2001:db8::/32'; label='SmokeV6'; vlan=100 }
)
} | ConvertTo-Json -Depth 10 | Out-File -FilePath $v6Path -Encoding utf8
$v6Topo = Import-Topology -Path $v6Path
$v6Drawio = Join-Path $tmp 'smoke-ipv6.drawio'
$v6Topo | Export-DrawIO -OutFile $v6Drawio
if (-not (Test-Path $v6Drawio)) { throw 'Export-DrawIO did not create IPv6 file' }
$v6xmlRaw = Get-Content $v6Drawio -Raw
if ($v6xmlRaw -notmatch [regex]::Escape('2001:db8::10')) { throw 'Export-DrawIO missing IPv6 address' }
$v6xml = [xml]$v6xmlRaw
$v6node = $v6xml.SelectSingleNode("//UserObject[@ip='2001:db8::10']")
}
$dualPath = Join-Path $tmp 'inventory-dual.json'
$dualInv | ConvertTo-Json -Depth 10 | Out-File -FilePath $dualPath -Encoding utf8
$dualTopo = Import-Inventory -Path $dualPath
$dualIps = @($dualTopo.Nodes.IP)
if ($dualIps -notcontains '10.0.0.1' -or $dualIps -notcontains '2001:db8::10') {
throw "Import-Inventory missing dual-stack node IPs: $($dualIps -join ', ')"
}
$dualDrawio = Join-Path $tmp 'smoke-dual.drawio'
$dualTopo | Export-DrawIO -OutFile $dualDrawio
if (-not (Test-Path $dualDrawio)) { throw 'Export-DrawIO did not create dual-stack file' }
$dualXmlRaw = Get-Content $dualDrawio -Raw
if ($dualXmlRaw -notmatch [regex]::Escape('10.0.0.1')) { throw 'Export-DrawIO missing IPv4 address' }
if ($dualXmlRaw -notmatch [regex]::Escape('2001:db8::10')) { throw 'Export-DrawIO missing IPv6 address' }
$dualXml = [xml]$dualXmlRaw
$v4node = $dualXml.SelectSingleNode("//UserObject[@ip='10.0.0.1']")
$v6node = $dualXml.SelectSingleNode("//UserObject[@ip='2001:db8::10']")
if ($null -eq $v4node) { throw 'Export-DrawIO missing UserObject for IPv4 node' }
if ($null -eq $v6node) { throw 'Export-DrawIO missing UserObject for IPv6 node' }
$v6parent = $v6node.mxCell.parent
if ([string]::IsNullOrWhiteSpace($v6parent) -or $v6parent -eq '1') {
throw "IPv6 node was not parented into a subnet container (parent='$v6parent')"
}
Write-Host "Export-DrawIO IPv6 OK: $v6Drawio (parent=$v6parent)"
Write-Host "Export-DrawIO dual-stack Import-Inventory OK: $dualDrawio (v6 parent=$v6parent)"
# record candidate evidence
$manifest = Import-PowerShellDataFile $stageModule
Write-Host "Candidate commit: $env:GITHUB_SHA"
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`$false` / `$null` (indeterminate, e.g. local send failure). Optional
`-TcpFallbackPort` can promote ICMP-silent hosts. DrawIO paints unknown gray.
- **Packaged CI smoke** imports every `FunctionsToExport` entry, uses
`actions/checkout@v7`, and asserts offline dual-stack DrawIO parenting.
`actions/checkout@v7`, and asserts offline dual-stack DrawIO via
`Import-Inventory` (v4 + v6 inventory JSON, not a hand-built topology).

### Fixed
- **`Invoke-SnmpWalk` accepts IPv6 `TargetIP`.** Validation was IPv4/FQDN-only,
Expand Down