feat: add two-tier version gating (introduced vs default) for cmdlets

Replace the service-layer RequireSdn hard block with a cmdlet-level
RequireVersion helper in PveCmdletBase that supports two tiers:

- Introduced version: hard fail — the API endpoint doesn't exist
- Default version: warning only — feature exists but may not be
  enabled; users who manually enabled it can proceed

Applied to:
- SDN Zone/VNet/Subnet: introduced 6.2, default 8.0
- SDN IPAM/DNS/Controller: introduced 6.2, default 8.1
- Import-PveVmDisk, Import-PveOva: introduced 8.1

Also fixes integration tests:
- Remove duplicate OVA Import context
- Use systemd calendar format for backup schedule (PVE 9)
- Add SDN IPAM/DNS/Controller read-only integration tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clint Branham
2026-03-21 08:40:23 -05:00
parent c6fd0d36fc
commit 27ecca6251
23 changed files with 117 additions and 28 deletions
@@ -826,6 +826,35 @@ Describe 'Integration Tests' -Tag 'Integration' {
}
}
# -----------------------------------------------------------------------
Context 'SDN — IPAM, DNS, Controllers' {
It 'Should list SDN IPAM plugins (Get-PveSdnIpam)' {
if (Skip-IfNoTarget) { return }
if ($script:SkipSdn) { Set-ItResult -Skipped -Because $script:SkipSdn; return }
# PVE always has a built-in 'pve' IPAM plugin
$ipams = Get-PveSdnIpam
$ipams | Should -Not -BeNullOrEmpty
($ipams | Where-Object { $_.Type -eq 'pve' }) | Should -Not -BeNullOrEmpty
}
It 'Should list SDN DNS plugins (Get-PveSdnDns)' {
if (Skip-IfNoTarget) { return }
if ($script:SkipSdn) { Set-ItResult -Skipped -Because $script:SkipSdn; return }
# Zero DNS plugins is acceptable; just verify no throw.
{ Get-PveSdnDns -ErrorAction Stop } | Should -Not -Throw
}
It 'Should list SDN controllers (Get-PveSdnController)' {
if (Skip-IfNoTarget) { return }
if ($script:SkipSdn) { Set-ItResult -Skipped -Because $script:SkipSdn; return }
# Zero controllers is acceptable; just verify no throw.
{ Get-PveSdnController -ErrorAction Stop } | Should -Not -Throw
}
}
# -----------------------------------------------------------------------
Context 'Templates' {
It 'Should list templates' {