mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-13 07:36:52 +00:00
a72642d203
Add 35 new cmdlets bringing the total to 118: - Firewall (21): rules, groups, aliases, IP sets, options at cluster/node/VM/container levels - Backup (5): ad-hoc vzdump and scheduled backup job CRUD - SDN IPAM/DNS/Controller (9): plugin management for SDN subsystem Also includes: - Fix: Remove-PveRole now has ConfirmImpact.High - Fix: URL-encode snapshot names in API paths - Refactor: extract auth header strings to constants in PveHttpClient - Add PSGallery version badge to README - Full test coverage: 11 JSON fixtures, xUnit model tests, Pester unit tests, and integration tests for firewall/backup/OVA import - Updated manifest, format file, CHANGELOG, README, API coverage docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
780 lines
37 KiB
Markdown
780 lines
37 KiB
Markdown
# PSProxmoxVE Module Review Report
|
|
|
|
```
|
|
Scan date: 2026-03-21
|
|
Prior report date: 2026-03-19
|
|
```
|
|
|
|
**Reviewer:** Claude Code (Opus 4.6)
|
|
**Module Version:** 0.1.0-preview
|
|
**Repository:** PSProxmoxVE (C# binary PowerShell module)
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
**Delta since last scan: 22 fixed | 2 new findings | 0 regressed | 4 still open**
|
|
|
|
1. **Significant progress since prior scan** — 22 of 28 findings from the initial report have been resolved, including all Critical items.
|
|
2. **83 cmdlets** (up from 66) covering VMs, containers (with snapshots and migration), storage, networking, SDN (zones, VNets, subnets), users/roles/permissions, templates, cloud-init, OVA/disk import, and tasks.
|
|
3. **All prior Critical items resolved**: publish workflow added, README updated with `Install-Module`, ReleaseNotes in manifest.
|
|
4. **Community files complete**: CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, .gitattributes, issue/PR templates all added.
|
|
5. **Code quality improvements**: HelpMessage on all parameters, WriteVerbose throughout, ValidateRange on VmId, ConfirmImpact.High on Stop/Reset-PveVm, Reset verb constant fixed.
|
|
6. **MAML help file** present (PSProxmoxVE.dll-Help.xml) with 75 cmdlet documentation files in docs/cmdlets/.
|
|
7. **Remaining gaps**: No IconUri in manifest, Remove-PveRole missing ConfirmImpact.High, firewall/backup/pool cmdlets not yet implemented.
|
|
8. **Excellent test coverage**: 100% Pester unit tests, 84% integration test coverage, xUnit model tests with PVE 8 & 9 fixtures.
|
|
9. **Security posture is clean**: No hardcoded secrets, HTTPS enforced, SkipCertificateCheck emits warning, all dependencies pinned.
|
|
10. **Module is near PSGallery-ready** — no blocking issues remain.
|
|
|
|
---
|
|
|
|
## Phase 1 — Repository Inventory & Structure
|
|
|
|
### Directory Tree (depth ≤ 4)
|
|
|
|
```
|
|
PSProxmoxVE/
|
|
├── PSProxmoxVE.sln
|
|
├── README.md
|
|
├── LICENSE (MIT)
|
|
├── CHANGELOG.md
|
|
├── CONTRIBUTING.md
|
|
├── CODE_OF_CONDUCT.md
|
|
├── SECURITY.md
|
|
├── .editorconfig
|
|
├── .gitignore
|
|
├── .gitattributes
|
|
├── CLAUDE.md
|
|
├── REVIEW_REPORT.md
|
|
├── .github/
|
|
│ ├── ISSUE_TEMPLATE/
|
|
│ │ ├── bug_report.yml
|
|
│ │ └── feature_request.yml
|
|
│ ├── pull_request_template.md
|
|
│ └── workflows/
|
|
│ ├── build.yml
|
|
│ ├── unit-tests.yml
|
|
│ ├── integration-tests.yml
|
|
│ └── publish.yml
|
|
├── docs/
|
|
│ ├── PVE_API_COVERAGE.md
|
|
│ └── cmdlets/ (75 cmdlet documentation files)
|
|
├── src/
|
|
│ ├── PSProxmoxVE/
|
|
│ │ ├── PSProxmoxVE.csproj
|
|
│ │ ├── PSProxmoxVE.psd1
|
|
│ │ ├── PSProxmoxVE.format.ps1xml
|
|
│ │ ├── PSProxmoxVE.dll-Help.xml
|
|
│ │ ├── ModuleState.cs
|
|
│ │ └── Cmdlets/
|
|
│ │ ├── PveCmdletBase.cs
|
|
│ │ ├── CloudInit/ (3 cmdlets)
|
|
│ │ ├── Connection/ (3 cmdlets)
|
|
│ │ ├── Containers/ (14 cmdlets)
|
|
│ │ ├── Network/ (14 cmdlets)
|
|
│ │ ├── Nodes/ (2 cmdlets)
|
|
│ │ ├── Snapshots/ (4 cmdlets)
|
|
│ │ ├── Storage/ (6 cmdlets)
|
|
│ │ ├── Tasks/ (2 cmdlets)
|
|
│ │ ├── Templates/ (4 cmdlets)
|
|
│ │ ├── Users/ (12 cmdlets)
|
|
│ │ └── Vms/ (19 cmdlets)
|
|
│ └── PSProxmoxVE.Core/
|
|
│ ├── PSProxmoxVE.Core.csproj
|
|
│ ├── Authentication/ (PveAuthenticator, PveAuthMode, PveSession, PveVersion)
|
|
│ ├── Client/ (PveHttpClient)
|
|
│ ├── Exceptions/ (7 exception types)
|
|
│ ├── Models/ (25 model classes)
|
|
│ └── Services/ (11 service classes)
|
|
├── tests/
|
|
│ ├── PSProxmoxVE.Core.Tests/ (xUnit)
|
|
│ │ ├── Authentication/ (3 test files)
|
|
│ │ ├── Fixtures/ (23 JSON fixtures)
|
|
│ │ ├── Models/ (10 test files)
|
|
│ │ └── TestHelper.cs
|
|
│ ├── PSProxmoxVE.Tests/ (Pester 5)
|
|
│ │ ├── _TestHelper.ps1
|
|
│ │ ├── CloudInit/
|
|
│ │ ├── Connection/ (3 test files)
|
|
│ │ ├── Containers/ (4 test files)
|
|
│ │ ├── Network/ (3 test files)
|
|
│ │ ├── Nodes/ (1 test file)
|
|
│ │ ├── Snapshots/ (1 test file)
|
|
│ │ ├── Storage/ (3 test files)
|
|
│ │ ├── Tasks/ (1 test file)
|
|
│ │ ├── Templates/ (1 test file)
|
|
│ │ ├── Users/ (3 test files)
|
|
│ │ ├── Vms/ (9 test files)
|
|
│ │ └── Integration/ (1 comprehensive test file)
|
|
│ └── infrastructure/ (Terraform, Dockerfile, scripts for CI)
|
|
└── tools/
|
|
```
|
|
|
|
### Project Layout
|
|
|
|
| Item | Value |
|
|
|---|---|
|
|
| Solution | `PSProxmoxVE.sln` |
|
|
| Main project | `src/PSProxmoxVE/PSProxmoxVE.csproj` |
|
|
| Core library | `src/PSProxmoxVE.Core/PSProxmoxVE.Core.csproj` |
|
|
| Test project (xUnit) | `tests/PSProxmoxVE.Core.Tests/PSProxmoxVE.Core.Tests.csproj` |
|
|
| Test project (Pester) | `tests/PSProxmoxVE.Tests/` |
|
|
| Target Frameworks | `netstandard2.0`, `net9.0`, `net48` |
|
|
| Language Version | C# 10.0 |
|
|
| Nullable | Enabled |
|
|
| Assembly Names | `PSProxmoxVE`, `PSProxmoxVE.Core` |
|
|
|
|
### CI/CD Workflows
|
|
|
|
| Workflow | Purpose |
|
|
|---|---|
|
|
| `build.yml` | Build + xUnit tests on net48 (Windows) and net9.0 (Windows + Ubuntu) |
|
|
| `unit-tests.yml` | Build + Pester tests across PS 5.1/7.5 on Windows/Ubuntu/macOS |
|
|
| `integration-tests.yml` | Full integration tests against nested PVE 8 + PVE 9 instances |
|
|
| `publish.yml` | Tag-triggered publish to PSGallery + GitHub Release creation |
|
|
|
|
### Inventory Checklist
|
|
|
|
| Item | Present | Prior Status |
|
|
|---|---|---|
|
|
| Solution file (`.sln`) | Yes | Open |
|
|
| Module manifest (`.psd1`) | Yes | Open |
|
|
| Format definitions (`.format.ps1xml`) | Yes | Open |
|
|
| MAML help (`.dll-Help.xml`) | Yes | New |
|
|
| `.editorconfig` | Yes | Open |
|
|
| `.gitignore` | Yes | Open |
|
|
| `.gitattributes` | Yes | Fixed |
|
|
| `LICENSE` (MIT) | Yes | Open |
|
|
| `CHANGELOG.md` | Yes | Open |
|
|
| `README.md` | Yes | Open |
|
|
| `CONTRIBUTING.md` | Yes | Fixed |
|
|
| `CODE_OF_CONDUCT.md` | Yes | Fixed |
|
|
| `SECURITY.md` | Yes | Fixed |
|
|
| `.github/ISSUE_TEMPLATE/` | Yes | Fixed |
|
|
| `.github/pull_request_template.md` | Yes | Fixed |
|
|
| PSGallery publish workflow | Yes | Fixed |
|
|
| `docs/PVE_API_COVERAGE.md` | Yes | New |
|
|
| `docs/cmdlets/` (75 files) | Yes | New |
|
|
|
|
### What's Missing
|
|
|
|
- [ ] `IconUri` in manifest PSData (cosmetic)
|
|
|
|
---
|
|
|
|
## Phase 2 — PVE API Coverage Audit
|
|
|
|
> **Note:** Coverage assessment based on source code analysis and the project's own `docs/PVE_API_COVERAGE.md`.
|
|
|
|
### Implemented Cmdlets by Category (83 total)
|
|
|
|
#### Connection (3 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Connect-PveServer` | `/access/ticket` | POST | Open |
|
|
| `Disconnect-PveServer` | `/access/ticket` | DELETE | Open |
|
|
| `Test-PveConnection` | `/version` | GET | Open |
|
|
|
|
#### Nodes (2 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveNode` | `/nodes` | GET | Open |
|
|
| `Get-PveNodeStatus` | `/nodes/{node}/status` | GET | Open |
|
|
|
|
#### VMs / QEMU (19 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveVm` | `/nodes/{node}/qemu` | GET | Open |
|
|
| `New-PveVm` | `/nodes/{node}/qemu` | POST | Open |
|
|
| `Remove-PveVm` | `/nodes/{node}/qemu/{vmid}` | DELETE | Open |
|
|
| `Start-PveVm` | `/nodes/{node}/qemu/{vmid}/status/start` | POST | Open |
|
|
| `Stop-PveVm` | `/nodes/{node}/qemu/{vmid}/status/stop` | POST | Open |
|
|
| `Restart-PveVm` | `/nodes/{node}/qemu/{vmid}/status/reboot` | POST | Open |
|
|
| `Suspend-PveVm` | `/nodes/{node}/qemu/{vmid}/status/suspend` | POST | Open |
|
|
| `Resume-PveVm` | `/nodes/{node}/qemu/{vmid}/status/resume` | POST | Open |
|
|
| `Reset-PveVm` | `/nodes/{node}/qemu/{vmid}/status/reset` | POST | Open |
|
|
| `Copy-PveVm` | `/nodes/{node}/qemu/{vmid}/clone` | POST | Open |
|
|
| `Move-PveVm` | `/nodes/{node}/qemu/{vmid}/migrate` | POST | Open |
|
|
| `Get-PveVmConfig` | `/nodes/{node}/qemu/{vmid}/config` | GET | Open |
|
|
| `Set-PveVmConfig` | `/nodes/{node}/qemu/{vmid}/config` | PUT | Open |
|
|
| `Resize-PveVmDisk` | `/nodes/{node}/qemu/{vmid}/resize` | PUT | Open |
|
|
| `Import-PveVmDisk` | `/nodes/{node}/storage/{storage}/upload` | POST | New |
|
|
| `Import-PveOva` | Multiple (upload + config + import) | POST | New |
|
|
| `Test-PveVmGuestAgent` | `/nodes/{node}/qemu/{vmid}/agent/ping` | POST | Open |
|
|
| `Get-PveVmGuestNetwork` | `/nodes/{node}/qemu/{vmid}/agent/network-get-interfaces` | GET | Open |
|
|
| `Invoke-PveVmGuestExec` | `/nodes/{node}/qemu/{vmid}/agent/exec` | POST | Open |
|
|
|
|
#### Containers / LXC (10 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveContainer` | `/nodes/{node}/lxc` | GET | Open |
|
|
| `New-PveContainer` | `/nodes/{node}/lxc` | POST | Open |
|
|
| `Remove-PveContainer` | `/nodes/{node}/lxc/{vmid}` | DELETE | Open |
|
|
| `Start-PveContainer` | `/nodes/{node}/lxc/{vmid}/status/start` | POST | Open |
|
|
| `Stop-PveContainer` | `/nodes/{node}/lxc/{vmid}/status/stop` | POST | Open |
|
|
| `Restart-PveContainer` | `/nodes/{node}/lxc/{vmid}/status/shutdown` | POST | Open |
|
|
| `Copy-PveContainer` | `/nodes/{node}/lxc/{vmid}/clone` | POST | Open |
|
|
| `Move-PveContainer` | `/nodes/{node}/lxc/{vmid}/migrate` | POST | New |
|
|
| `Get-PveContainerConfig` | `/nodes/{node}/lxc/{vmid}/config` | GET | Open |
|
|
| `Set-PveContainerConfig` | `/nodes/{node}/lxc/{vmid}/config` | PUT | Open |
|
|
|
|
#### Container Snapshots (4 cmdlets — NEW)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveContainerSnapshot` | `/nodes/{node}/lxc/{vmid}/snapshot` | GET | New |
|
|
| `New-PveContainerSnapshot` | `/nodes/{node}/lxc/{vmid}/snapshot` | POST | New |
|
|
| `Remove-PveContainerSnapshot` | `/nodes/{node}/lxc/{vmid}/snapshot/{name}` | DELETE | New |
|
|
| `Restore-PveContainerSnapshot` | `/nodes/{node}/lxc/{vmid}/snapshot/{name}/rollback` | POST | New |
|
|
|
|
#### Storage (6 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveStorage` | `/storage` or `/nodes/{node}/storage` | GET | Open |
|
|
| `Get-PveStorageContent` | `/nodes/{node}/storage/{storage}/content` | GET | Open |
|
|
| `Send-PveFile` | `/nodes/{node}/storage/{storage}/upload` | POST | Open |
|
|
| `Invoke-PveStorageDownload` | `/nodes/{node}/storage/{storage}/download-url` | POST | Open |
|
|
| `New-PveStorage` | `/storage` | POST | Open |
|
|
| `Remove-PveStorage` | `/storage/{storage}` | DELETE | Open |
|
|
|
|
#### VM Snapshots (4 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveSnapshot` | `/nodes/{node}/qemu/{vmid}/snapshot` | GET | Open |
|
|
| `New-PveSnapshot` | `/nodes/{node}/qemu/{vmid}/snapshot` | POST | Open |
|
|
| `Remove-PveSnapshot` | `/nodes/{node}/qemu/{vmid}/snapshot/{name}` | DELETE | Open |
|
|
| `Restore-PveSnapshot` | `/nodes/{node}/qemu/{vmid}/snapshot/{name}/rollback` | POST | Open |
|
|
|
|
#### Networking (5 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveNetwork` | `/nodes/{node}/network` | GET | Open |
|
|
| `New-PveNetwork` | `/nodes/{node}/network` | POST | Open |
|
|
| `Set-PveNetwork` | `/nodes/{node}/network/{iface}` | PUT | Open |
|
|
| `Remove-PveNetwork` | `/nodes/{node}/network/{iface}` | DELETE | Open |
|
|
| `Invoke-PveNetworkApply` | `/nodes/{node}/network` | PUT | Open |
|
|
|
|
#### SDN (9 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveSdnZone` | `/cluster/sdn/zones` | GET | Open |
|
|
| `New-PveSdnZone` | `/cluster/sdn/zones` | POST | Open |
|
|
| `Remove-PveSdnZone` | `/cluster/sdn/zones/{zone}` | DELETE | Open |
|
|
| `Get-PveSdnVnet` | `/cluster/sdn/vnets` | GET | Open |
|
|
| `New-PveSdnVnet` | `/cluster/sdn/vnets` | POST | Open |
|
|
| `Remove-PveSdnVnet` | `/cluster/sdn/vnets/{vnet}` | DELETE | Open |
|
|
| `Get-PveSdnSubnet` | `/cluster/sdn/vnets/{vnet}/subnets` | GET | New |
|
|
| `New-PveSdnSubnet` | `/cluster/sdn/vnets/{vnet}/subnets` | POST | New |
|
|
| `Remove-PveSdnSubnet` | `/cluster/sdn/vnets/{vnet}/subnets/{subnet}` | DELETE | New |
|
|
|
|
#### Users / ACLs / Tokens (12 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveUser` | `/access/users` | GET | Open |
|
|
| `New-PveUser` | `/access/users` | POST | Open |
|
|
| `Remove-PveUser` | `/access/users/{userid}` | DELETE | Open |
|
|
| `Set-PveUser` | `/access/users/{userid}` | PUT | Open |
|
|
| `Get-PveRole` | `/access/roles` | GET | Open |
|
|
| `New-PveRole` | `/access/roles` | POST | Open |
|
|
| `Remove-PveRole` | `/access/roles/{roleid}` | DELETE | Open |
|
|
| `Get-PvePermission` | `/access/acl` | GET | Open |
|
|
| `Set-PvePermission` | `/access/acl` | PUT | Open |
|
|
| `Get-PveApiToken` | `/access/users/{userid}/token` | GET | Open |
|
|
| `New-PveApiToken` | `/access/users/{userid}/token/{tokenid}` | POST | Open |
|
|
| `Remove-PveApiToken` | `/access/users/{userid}/token/{tokenid}` | DELETE | Open |
|
|
|
|
#### Templates (4 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveTemplate` | `/nodes/{node}/qemu` (filtered) | GET | Open |
|
|
| `New-PveTemplate` | `/nodes/{node}/qemu/{vmid}/template` | POST | Open |
|
|
| `Remove-PveTemplate` | `/nodes/{node}/qemu/{vmid}` | DELETE | Open |
|
|
| `New-PveVmFromTemplate` | `/nodes/{node}/qemu/{vmid}/clone` | POST | Open |
|
|
|
|
#### Cloud-Init (3 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveCloudInitConfig` | `/nodes/{node}/qemu/{vmid}/config` | GET | Open |
|
|
| `Set-PveCloudInitConfig` | `/nodes/{node}/qemu/{vmid}/config` | PUT | Open |
|
|
| `Invoke-PveCloudInitRegenerate` | `/nodes/{node}/qemu/{vmid}/cloudinit` | PUT | Open |
|
|
|
|
#### Tasks (2 cmdlets)
|
|
| Cmdlet | API Endpoint | Method | Prior Status |
|
|
|---|---|---|---|
|
|
| `Get-PveTask` | `/nodes/{node}/tasks/{upid}/status` | GET | Open |
|
|
| `Wait-PveTask` | `/nodes/{node}/tasks/{upid}/status` (polling) | GET | Open |
|
|
|
|
### Missing API Coverage by Functional Area
|
|
|
|
| Area | Key Missing Endpoints | Priority | Prior Status |
|
|
|---|---|---|---|
|
|
| **Firewall** | `/cluster/firewall/*`, `/nodes/{node}/firewall/*`, `/nodes/{node}/qemu/{vmid}/firewall/*` | High | Open |
|
|
| **Backup / vzdump** | `/nodes/{node}/vzdump`, `/cluster/backup/*` | High | Open |
|
|
| **Pools** | `/pools`, `/pools/{poolid}` (CRUD) | Medium | Open |
|
|
| **HA** | `/cluster/ha/*` (groups, resources, status) | Medium | Open |
|
|
| **Ceph** | `/nodes/{node}/ceph/*` (OSD, pool, mon, fs) | Medium | Open |
|
|
| **Replication** | `/cluster/replication` (CRUD) | Low | Open |
|
|
| **Access Groups** | `/access/groups` (CRUD) | Low | Open |
|
|
| **Access Domains** | `/access/domains` (CRUD) | Low | Open |
|
|
| **PBS Integration** | Proxmox Backup Server operations | Low | Open |
|
|
| **Cluster Config** | `/cluster/config/*` (join, nodes, totem) | Low | Open |
|
|
| **ACME** | `/cluster/acme/*`, `/nodes/{node}/certificates/*` | Low | Open |
|
|
| **Node Management** | `/nodes/{node}/apt/*`, `/nodes/{node}/disks/*`, `/nodes/{node}/services/*` | Low | Open |
|
|
| **Metrics** | `/cluster/metrics/*` | Low | Open |
|
|
| **SDN IPAM/DNS/Controllers** | `/cluster/sdn/ipams/*`, `/cluster/sdn/dns/*`, `/cluster/sdn/controllers/*` | Low | New |
|
|
| **VM Agent (extended)** | Additional agent endpoints (file-read, file-write, os-info) | Low | Open |
|
|
|
|
### High-Value Gaps
|
|
|
|
1. **Firewall management** — Critical for security automation. No cmdlets for creating/managing firewall rules at cluster, node, or VM level.
|
|
2. **Backup/restore (vzdump)** — Essential for DR automation. No cmdlets for creating backups, managing schedules, or restoring.
|
|
3. **Pool management** — Required for multi-tenant environments. No cmdlets for creating/managing resource pools.
|
|
|
|
---
|
|
|
|
## Phase 3 — Code Quality & Best Practices
|
|
|
|
### 3a. PowerShell Module Design
|
|
|
|
#### Cmdlet Naming
|
|
- **All cmdlets use approved PowerShell verbs** via verb class constants (`VerbsCommon.Get`, `VerbsLifecycle.Start`, etc.).
|
|
- Noun prefix `Pve` is consistent across all 83 cmdlets.
|
|
- Previous finding about `Reset-PveVm` using a string literal has been fixed — now uses `VerbsCommon.Reset`.
|
|
|
|
#### Parameter Design
|
|
- `[Parameter(Mandatory = ...)]` used appropriately throughout.
|
|
- `ValueFromPipelineByPropertyName = true` used on `Node`, `VmId`, and similar parameters.
|
|
- `Position` attributes used on key parameters.
|
|
- `ValidateSet`, `ValidateRange(100, 999999999)`, `ValidateNotNullOrEmpty`, `ValidatePattern` used where appropriate.
|
|
- **HelpMessage** present on virtually all parameters (previously missing).
|
|
|
|
#### ShouldProcess / WhatIf / Confirm
|
|
- Every destructive/mutating cmdlet implements `SupportsShouldProcess = true`.
|
|
- `ConfirmImpact = ConfirmImpact.High` on all `Remove-*` cmdlets, `Stop-PveVm`, `Reset-PveVm`, `New-PveTemplate`, `Restore-PveSnapshot`, `Restore-PveContainerSnapshot`.
|
|
- **Gap**: `Remove-PveRole` does not set `ConfirmImpact.High` — deleting a role is a significant operation.
|
|
|
|
#### OutputType
|
|
- `[OutputType]` attributes present on all 83 cmdlets.
|
|
|
|
#### Pipeline Support
|
|
- All cmdlets use `ProcessRecord` for pipeline processing.
|
|
- `Get-PveVm`, `Get-PveContainer` output objects with `Node` and `VmId` enabling chaining.
|
|
|
|
#### Error Handling
|
|
- `ThrowTerminatingError` used appropriately for fatal conditions.
|
|
- `WriteWarning` used for non-fatal conditions.
|
|
- Custom exception hierarchy provides structured errors.
|
|
|
|
### 3b. C# Code Quality
|
|
|
|
#### Null-Reference Safety
|
|
- `<Nullable>enable</Nullable>` in both `.csproj` files.
|
|
- Consistent use of nullable annotations, null guards (`?? throw`), and null-coalescing patterns.
|
|
- No null-forgiving operators (`!`) used.
|
|
|
|
#### Async/Await Pattern
|
|
- All HTTP operations are async in `PveHttpClient` with `.ConfigureAwait(false)`.
|
|
- Sync wrappers use `.GetAwaiter().GetResult()` — standard for PowerShell binary modules.
|
|
- Low deadlock risk given the single pipeline thread model.
|
|
|
|
#### IDisposable Correctness
|
|
- `PveHttpClient` implements `IDisposable` correctly with `_disposed` flag.
|
|
- All service methods use `using var client = new PveHttpClient(session)`.
|
|
- File upload uses framework-conditional async disposal.
|
|
|
|
#### Exception Handling
|
|
- Well-defined exception hierarchy (7 custom types) with context properties.
|
|
- `PveHttpClient.SendAsync` wraps `HttpRequestException` in `PveApiException`.
|
|
- Silent catches are intentional and documented (node polling, status enrichment).
|
|
|
|
#### Magic Strings
|
|
- Auth header names inline (minor, not problematic).
|
|
- API resource paths constructed inline (pragmatic for codebase size).
|
|
- `RandomNumberGenerator` used for boundary generation (previously `new Random()`).
|
|
|
|
#### Logging / Verbose Output
|
|
- `WriteVerbose` used extensively throughout cmdlets (previously missing).
|
|
- `WriteProgress` used in `Send-PveFile`, `Import-PveOva`, and `Wait-PveTask`.
|
|
|
|
### 3c. General Hygiene
|
|
|
|
- No unused `using` directives detected.
|
|
- No commented-out blocks or dead code.
|
|
- Zero TODO/FIXME/HACK markers.
|
|
- Consistent code style matching `.editorconfig`.
|
|
- XML doc comments on all public types and cmdlet classes.
|
|
- `CS1591` no longer suppressed in Core project.
|
|
|
|
### Code Quality Findings
|
|
|
|
| ID | File | Line | Severity | Description | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| CQ1 | `RemovePveRoleCmdlet.cs` | 13 | Medium | Missing `ConfirmImpact.High` — deleting roles is significant | New |
|
|
| CQ2 | `PveHttpClient.cs` | 316-323 | Low | Auth header names (`PVEAPIToken=`, `CSRFPreventionToken`) could be constants | Open |
|
|
|
|
---
|
|
|
|
## Phase 4 — Testing Coverage Analysis
|
|
|
|
### Test Projects
|
|
|
|
| Project | Framework | Type | Runner |
|
|
|---|---|---|---|
|
|
| `PSProxmoxVE.Core.Tests` | xUnit 2.7 + Moq 4.20 | Unit tests (models, auth) | `dotnet test` |
|
|
| `PSProxmoxVE.Tests` | Pester 5 | Cmdlet + Integration tests | `Invoke-Pester` |
|
|
|
|
### xUnit Tests (Core Library)
|
|
|
|
| Test Area | Test File | ~Methods |
|
|
|---|---|---|
|
|
| Session lifecycle | `PveSessionTests.cs` | 9 |
|
|
| Authentication logic | `PveAuthenticatorTests.cs` | 7 |
|
|
| Version parsing | `PveVersionTests.cs` | 11 |
|
|
| Cluster models | `ClusterModelTests.cs` | 13 |
|
|
| Container models | `ContainerModelTests.cs` | 13 |
|
|
| Network models | `NetworkModelTests.cs` | 12 |
|
|
| Node models | `NodeModelTests.cs` | 13 |
|
|
| SDN models | `SdnModelTests.cs` | 17 |
|
|
| Snapshot models | `SnapshotModelTests.cs` | 9 |
|
|
| Storage models | `StorageModelTests.cs` | 19 |
|
|
| Task models | `TaskModelTests.cs` | 9 |
|
|
| User models | `UserModelTests.cs` | 24 |
|
|
| VM models | `VmModelTests.cs` | 18 |
|
|
|
|
**Total: ~174 xUnit tests** with PVE 8 and PVE 9 JSON fixtures.
|
|
|
|
### Pester Tests (30 files, ~500 tests)
|
|
|
|
All 83 cmdlets have Pester unit tests covering command metadata, parameter validation, ShouldProcess presence, and pipeline binding.
|
|
|
|
### Integration Tests
|
|
|
|
The integration test file covers 18+ major contexts with 90+ individual tests:
|
|
|
|
- Connection, Nodes, User/Role/Token CRUD, Permissions
|
|
- VM lifecycle (create, config, start/stop, reset, clone, resize, suspend/resume)
|
|
- Snapshot CRUD (VM and container)
|
|
- Storage (list, content, upload, create/remove, download)
|
|
- Network CRUD with apply/revert
|
|
- SDN zones/VNets/subnets CRUD
|
|
- Templates, Cloud-Init
|
|
- Container lifecycle (create, config, start/stop/restart, clone, snapshots)
|
|
- Linux VM provisioning (cloud image upload, disk import, cloud-init, guest agent)
|
|
|
|
**Setup/teardown**: AfterAll cleans up all created resources. Environment variables inject connection details. Tests skip gracefully when env vars are missing.
|
|
|
|
### Test Coverage Gap List
|
|
|
|
| Cmdlet | Unit Test | Integration Test | PVE 8 | PVE 9 | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| `Connect-PveServer` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Disconnect-PveServer` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Test-PveConnection` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PveNode` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PveNodeStatus` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PveVm` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveVm` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Remove-PveVm` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Start-PveVm` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Stop-PveVm` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Restart-PveVm` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Suspend-PveVm` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Resume-PveVm` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Reset-PveVm` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Copy-PveVm` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Move-PveVm` | ✓ | ✗ | — | — | Open |
|
|
| `Get-PveVmConfig` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Set-PveVmConfig` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Resize-PveVmDisk` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Import-PveVmDisk` | ✓ | ✓ | — | ✓ | New |
|
|
| `Import-PveOva` | ✓ | ✗ | — | — | New |
|
|
| `Test-PveVmGuestAgent` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Get-PveVmGuestNetwork` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Invoke-PveVmGuestExec` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Get-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `New-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Remove-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Start-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Stop-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Restart-PveContainer` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Copy-PveContainer` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Move-PveContainer` | ✓ | ✗ | — | — | New |
|
|
| `Get-PveContainerConfig` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Set-PveContainerConfig` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Get-PveContainerSnapshot` | ✓ | ✓ | — | ✓ | New |
|
|
| `New-PveContainerSnapshot` | ✓ | ✓ | — | ✓ | New |
|
|
| `Remove-PveContainerSnapshot` | ✓ | ✓ | — | ✓ | New |
|
|
| `Restore-PveContainerSnapshot` | ✓ | ✓ | — | ✓ | New |
|
|
| `Get-PveStorage` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveStorage` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Remove-PveStorage` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveStorageContent` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Send-PveFile` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Invoke-PveStorageDownload` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveSnapshot` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveSnapshot` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Remove-PveSnapshot` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Restore-PveSnapshot` | ✓ | ✗ | — | — | Open |
|
|
| `Get-PveNetwork` | ✓ | ✓ | — | ✓ | Open |
|
|
| `New-PveNetwork` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Set-PveNetwork` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Remove-PveNetwork` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Invoke-PveNetworkApply` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveSdnZone` | ✓ | ✓ | — | ✓ | Open |
|
|
| `New-PveSdnZone` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Remove-PveSdnZone` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveSdnVnet` | ✓ | ✓ | — | ✓ | Open |
|
|
| `New-PveSdnVnet` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Remove-PveSdnVnet` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveSdnSubnet` | ✓ | ✓ | — | ✓ | New |
|
|
| `New-PveSdnSubnet` | ✓ | ✓ | — | ✓ | New |
|
|
| `Remove-PveSdnSubnet` | ✓ | ✓ | — | ✓ | New |
|
|
| `Get-PveUser` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveUser` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Set-PveUser` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Remove-PveUser` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PveRole` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveRole` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Remove-PveRole` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PveApiToken` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `New-PveApiToken` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Remove-PveApiToken` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Get-PvePermission` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Set-PvePermission` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Get-PveTemplate` | ✓ | ✓ | — | ✓ | Open |
|
|
| `New-PveTemplate` | ✓ | ✗ | — | — | Open |
|
|
| `Remove-PveTemplate` | ✓ | ✗ | — | — | Open |
|
|
| `New-PveVmFromTemplate` | ✓ | ✗ | — | — | Open |
|
|
| `Get-PveCloudInitConfig` | ✓ | ✓ | — | ✓ | Open |
|
|
| `Set-PveCloudInitConfig` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Invoke-PveCloudInitRegenerate` | ✓ | ✓ | — | ✓ | Fixed |
|
|
| `Get-PveTask` | ✓ | ✓ | ✓ | ✓ | Open |
|
|
| `Wait-PveTask` | ✓ | ✓ | — | ✓ | Open |
|
|
|
|
**Summary**: 83/83 unit tested (100%), 70/83 integration tested (84%). Remaining gaps are for operations requiring multi-node clusters (`Move-PveVm`, `Move-PveContainer`), optional test assets (`Import-PveOva`), or template operations that would require extra setup.
|
|
|
|
---
|
|
|
|
## Phase 5 — Security Review
|
|
|
|
### 5.1 Credential Handling
|
|
|
|
| Aspect | Status | Details | Prior Status |
|
|
|---|---|---|---|
|
|
| PSCredential usage | **Good** | `Connect-PveServer` accepts `PSCredential` for password auth | Open |
|
|
| Password extraction | **Acceptable** | `NetworkCredential.Password` used only at API call time | Open |
|
|
| API token in memory | **Acceptable** | Stored as plain `string` in `PveSession.ApiToken` | Open |
|
|
| Credential logging | **Good** | No `WriteVerbose`/`WriteDebug` calls include credentials | Open |
|
|
| Ticket storage | **Good** | Tickets stored in `PveSession` only, not written to disk | Open |
|
|
| Session expiry | **Good** | 2-hour expiry detected via `IsExpired` property | Open |
|
|
|
|
### 5.2 TLS/HTTPS
|
|
|
|
| Aspect | Status | Details | Prior Status |
|
|
|---|---|---|---|
|
|
| HTTPS enforced | **Good** | `BaseUrl` always constructs `https://` URLs | Open |
|
|
| SkipCertificateCheck | **Good** | Explicit opt-in parameter on `Connect-PveServer` | Open |
|
|
| Warning on skip | **Good** | `WriteWarning` emitted with man-in-the-middle advisory | Fixed |
|
|
| TLS version | **Good** | Left to OS/runtime negotiation (no pinning) | Open |
|
|
| Port validation | **Good** | `ValidateRange(1, 65535)` on port parameter | Open |
|
|
|
|
### 5.3 Input Validation
|
|
|
|
| Aspect | Status | Details | Prior Status |
|
|
|---|---|---|---|
|
|
| VMID validation | **Good** | `[ValidateRange(100, 999999999)]` on all VmId parameters | Fixed |
|
|
| URL construction | **Good** | String interpolation with validated parameters | Open |
|
|
| User ID encoding | **Good** | `Uri.EscapeDataString()` used for user/token IDs in URLs | Open |
|
|
| API token format | **Good** | Regex validation in `PveAuthenticator` | Open |
|
|
| Path parameters | **Low risk** | Node/snapshot names not URL-encoded but come from validated sources | Open |
|
|
|
|
### 5.4 Dependency Security
|
|
|
|
| Package | Version | Pinned | Notes | Prior Status |
|
|
|---|---|---|---|---|
|
|
| `Newtonsoft.Json` | 13.0.3 | Yes | Latest stable, no known CVEs | Open |
|
|
| `System.Text.Json` | 8.0.5 | Yes | Latest 8.x patch | Open |
|
|
| `SharpCompress` | 0.38.0 | Yes | OVA/tar extraction support | New |
|
|
| `PowerShellStandard.Library` | 5.1.1 | Yes | PrivateAssets=all | Open |
|
|
| `System.Management.Automation` | 7.4.0 | Yes | PrivateAssets=all | Open |
|
|
|
|
All dependencies are pinned to exact versions.
|
|
|
|
### 5.5 Secret Scanning
|
|
|
|
No hardcoded credentials, tokens, or sensitive IPs found in source code. CI workflow uses GitHub Actions secrets with `::add-mask::` for test passwords.
|
|
|
|
### Security Findings
|
|
|
|
| ID | Area | File | Severity | Description | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| S1 | Input validation | `SnapshotService.cs`, `ContainerService.cs` | Low | Snapshot names and node names in URL paths are not URL-encoded — low risk as values come from validated/system sources | New |
|
|
|
|
---
|
|
|
|
## Phase 6 — PSGallery Publication Readiness
|
|
|
|
### 6.1 Module Manifest Assessment
|
|
|
|
| Field | Status | Value | Prior Status |
|
|
|---|---|---|---|
|
|
| `RootModule` | Pass | `PSProxmoxVE.dll` | Open |
|
|
| `ModuleVersion` | Pass | `0.1.0` | Open |
|
|
| `GUID` | Pass | `a3f7c2d1-84e5-4b9f-a061-3e2d8c5f1a7b` | Open |
|
|
| `Author` | Pass | `goodolclint` | Open |
|
|
| `CompanyName` | Pass | `Worklab` | Open |
|
|
| `Copyright` | Pass | `(c) 2026 goodolclint. All rights reserved.` | Open |
|
|
| `Description` | Pass | Meaningful | Open |
|
|
| `PowerShellVersion` | Pass | `5.1` | Open |
|
|
| `CompatiblePSEditions` | Pass | `Desktop`, `Core` | Open |
|
|
| `DotNetFrameworkVersion` | Pass | `4.8` | Open |
|
|
| `RequiredAssemblies` | Pass | Lists Core DLL and Newtonsoft.Json | Open |
|
|
| `FormatsToProcess` | Pass | `PSProxmoxVE.format.ps1xml` | Open |
|
|
| `CmdletsToExport` | Pass | Explicit list of all cmdlets | Open |
|
|
| `FunctionsToExport` | Pass | Empty (binary module) | Open |
|
|
| `AliasesToExport` | Pass | 7 aliases defined | New |
|
|
| `Prerelease` | Pass | `preview` | Open |
|
|
| `Tags` | Pass | 8 relevant tags | Open |
|
|
| `LicenseUri` | Pass | GitHub LICENSE | Open |
|
|
| `ProjectUri` | Pass | GitHub repo | Open |
|
|
| `HelpInfoURI` | Pass | `docs/cmdlets` | Fixed |
|
|
| `ReleaseNotes` | Pass | Present in PSData | Fixed |
|
|
| `IconUri` | **Fail** | Not present | Open |
|
|
|
|
### 6.2 License
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| LICENSE file present | Pass | MIT License at repo root | Open |
|
|
| OSI-approved license | Pass | MIT | Open |
|
|
| LicenseUri in manifest | Pass | Points to GitHub LICENSE | Open |
|
|
|
|
### 6.3 README Quality
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| Installation instructions | Pass | `Install-Module PSProxmoxVE` | Fixed |
|
|
| Quick-start examples | Pass | Multiple scenarios | Open |
|
|
| Authentication guide | Pass | Ticket + API token documented | Open |
|
|
| Badges | Pass | Build, Unit Tests, License badges | Fixed |
|
|
| Cmdlet reference | Pass | All cmdlets listed | Open |
|
|
| Known limitations | Pass | Documented | Open |
|
|
| Contributing section | Pass | References CONTRIBUTING.md | Open |
|
|
|
|
### 6.4 Build & Publish Pipeline
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| Build workflow | Pass | net48 + net9.0, Windows + Ubuntu | Open |
|
|
| Unit test workflow | Pass | PS 5.1/7.5, Windows/Ubuntu/macOS | Open |
|
|
| Integration test workflow | Pass | PVE 8 + PVE 9 | Open |
|
|
| Publish workflow | Pass | Tag-triggered, PSGallery + GitHub Release | Fixed |
|
|
| API key handling | Pass | Via `PSGALLERY_API_KEY` secret | Fixed |
|
|
|
|
### 6.5 Versioning
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| CHANGELOG format | Pass | Keep a Changelog with versioned entry | Open |
|
|
| Versioned release | Pass | `0.1.0-preview` entry present | Fixed |
|
|
| Commit conventions | Pass | Conventional Commits used consistently | Open |
|
|
|
|
### PSGallery Readiness Checklist
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| Module manifest complete | Pass | All required fields populated | Open |
|
|
| License present and OSI-approved | Pass | MIT | Open |
|
|
| README with install instructions | Pass | PSGallery install documented | Fixed |
|
|
| Publish pipeline configured | Pass | `publish.yml` on tag push | Fixed |
|
|
| ReleaseNotes present | Pass | In PSData section | Fixed |
|
|
| IconUri | **Fail** | Missing — cosmetic only | Open |
|
|
| MAML help file | Pass | `PSProxmoxVE.dll-Help.xml` present | New |
|
|
|
|
---
|
|
|
|
## Phase 7 — Community & Repo Maintenance Standards
|
|
|
|
| Check | Pass/Fail | Notes | Prior Status |
|
|
|---|---|---|---|
|
|
| `README.md` | Pass | Comprehensive with badges | Open |
|
|
| `LICENSE` | Pass | MIT | Open |
|
|
| `CHANGELOG.md` | Pass | Keep a Changelog format with versioned entry | Open |
|
|
| `CONTRIBUTING.md` | Pass | Dev setup, coding standards, test instructions, PR process | Fixed |
|
|
| `CODE_OF_CONDUCT.md` | Pass | Contributor Covenant v2.1 | Fixed |
|
|
| `SECURITY.md` | Pass | Vulnerability disclosure policy, 48h response SLA | Fixed |
|
|
| `.editorconfig` | Pass | Comprehensive rules | Open |
|
|
| `.gitignore` | Pass | Build outputs, IDE files, test results | Open |
|
|
| `.gitattributes` | Pass | Line ending normalization, binary detection | Fixed |
|
|
| Issue templates | Pass | Bug report + feature request (YAML format) | Fixed |
|
|
| PR template | Pass | Summary, type checkboxes, checklist | Fixed |
|
|
| Conventional commits | Pass | Consistent in recent history | Open |
|
|
| Default branch `main` | Pass | Confirmed | Open |
|
|
| API coverage documentation | Pass | `docs/PVE_API_COVERAGE.md` | New |
|
|
| Cmdlet documentation | Pass | 75 files in `docs/cmdlets/` | New |
|
|
|
|
### Recommended Branch Protection (cannot verify via API)
|
|
|
|
- Require PR reviews before merge
|
|
- Require status checks (build + unit tests + integration tests)
|
|
- Require linear history or squash merging
|
|
|
|
---
|
|
|
|
## Phase 8 — Prioritized Recommendations
|
|
|
|
### 🔴 Critical (blocks PSGallery publication or is a security risk)
|
|
|
|
**None** — all prior Critical items have been resolved.
|
|
|
|
### 🟠 High (significantly impacts quality or community adoption)
|
|
|
|
| # | What | Where | Why | Fix | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| H1 | **No firewall cmdlets** | Module | High-value gap for security automation — most requested feature area | Implement firewall rule CRUD for cluster/node/VM | Open |
|
|
| H2 | **No backup/vzdump cmdlets** | Module | Essential for DR automation scenarios | Implement vzdump and backup schedule management | Open |
|
|
|
|
### 🟡 Medium (best practice gaps, test coverage holes)
|
|
|
|
| # | What | Where | Why | Fix | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| M1 | `Remove-PveRole` missing `ConfirmImpact.High` | `RemovePveRoleCmdlet.cs:13` | Deleting roles is a significant, potentially disruptive operation | Add `ConfirmImpact = ConfirmImpact.High` | New |
|
|
| M2 | No pool management | Module | Useful for multi-tenant environments | Implement pool CRUD | Open |
|
|
| M3 | `Move-PveVm` / `Move-PveContainer` lack integration tests | Integration tests | Migration is untested end-to-end (requires multi-node) | Add integration tests when multi-node CI is available | Open |
|
|
| M4 | `Import-PveOva` lacks integration test | Integration tests | OVA import only tested at parameter level | Add to integration tests (requires OVA test asset) | New |
|
|
| M5 | URL-encode snapshot/node names in API paths | `SnapshotService.cs`, `ContainerService.cs` | Defense-in-depth against path injection (low risk) | Apply `Uri.EscapeDataString()` to path parameters | New |
|
|
|
|
### 🟢 Low / Nice-to-have (polish, discoverability, stretch goals)
|
|
|
|
| # | What | Where | Why | Fix | Prior Status |
|
|
|---|---|---|---|---|---|
|
|
| L1 | No `IconUri` in manifest | `PSProxmoxVE.psd1` | Improves PSGallery listing appearance | Create module icon, host it, add URI | Open |
|
|
| L2 | Auth header magic strings | `PveHttpClient.cs:316-323` | Minor code quality — could be named constants | Extract to `const string` fields | Open |
|
|
| L3 | HA/Ceph/Replication cmdlets | Module | Lower-priority API coverage gaps | Implement as demand grows | Open |
|
|
| L4 | Access groups/domains cmdlets | Module | Useful for LDAP/AD integration | Implement `/access/groups`, `/access/domains` CRUD | Open |
|
|
| L5 | PSGallery version badge | `README.md` | Shows published version to visitors | Add PSGallery badge after first publish | New |
|
|
| L6 | SDN IPAM/DNS/Controller cmdlets | Module | Complete SDN management surface | Implement as demand grows | New |
|
|
|
|
---
|
|
|
|
## Summary Statistics
|
|
|
|
| Metric | This Scan | Prior Scan | Delta |
|
|
|---|---|---|---|
|
|
| Total cmdlets | 83 | 66 | +17 |
|
|
| Cmdlets with ShouldProcess | All mutating | All mutating | — |
|
|
| Cmdlets with OutputType | 83 (100%) | 66 (100%) | — |
|
|
| Cmdlets with HelpMessage | 83 (100%) | 0 (0%) | +83 |
|
|
| xUnit test files | 13 | 13 | — |
|
|
| Pester test files | 30 | 26 | +4 |
|
|
| Integration test coverage | 84% | ~70% | +14% |
|
|
| PVE API areas covered | 12 of ~20 | 10 of ~20 | +2 |
|
|
| Critical issues | 0 | 3 | -3 |
|
|
| High issues | 2 | 8 | -6 |
|
|
| Medium issues | 5 | 10 | -5 |
|
|
| Low issues | 6 | 10 | -4 |
|
|
| **Total issues** | **13** | **31** | **-18** |
|
|
| NuGet dependencies (runtime) | 3 | 2 | +1 (SharpCompress) |
|
|
| Security vulnerabilities | 0 | 0 | — |
|
|
| Community files present | 9/9 | 3/9 | +6 |
|
|
| Documentation files | 78 | 1 | +77 |
|