Commit Graph

311 Commits

Author SHA1 Message Date
Clint Branham a1d9550d83 fix: surface HttpClient timeouts as PveApiException(RequestTimeout)
When HttpClient.Timeout elapses, .NET throws TaskCanceledException — not
HttpRequestException — so the existing catch in PveHttpClient.SendAsync
missed it and callers got a raw stack trace. With -TimeoutSeconds now
configurable and documented, this gap became user-visible.

In .NET 5+ HttpClient surfaces transport timeouts as TaskCanceledException
with a TimeoutException inner; user-driven token cancellation does not.
Catch by that inner-type signature and rethrow as PveApiException with
HttpStatusCode.RequestTimeout, the resource path, and a message that
reports the configured timeout.

Adds SendAsync_TimeoutFires_ThrowsPveApiExceptionWithRequestTimeout which
swaps in a delaying HttpMessageHandler with a 50ms timeout to exercise
the path deterministically. Drops the redundant
DefaultSessionTimeoutIs100Seconds test (covered by
PveSessionTests.Timeout_DefaultIs100Seconds and the existing flow-through
test).

Addresses PR #61 review feedback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:17:31 -05:00
Clint Branham ea2bcdc336 Merge main into fix/http-client-timeout
Resolves findings.json conflict — F086 (from #60, merged into main) and
F087 (this branch) both append to the trailing findings array. Kept both
entries, in numeric order.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:17:20 -05:00
GoodOlClint 239a6b8fe9 Merge pull request #60 from GoodOlClint/fix/disk-size-unit-normalization
fix: normalize -DiskSize/-RootFsSize before sending to PVE (#58)
2026-05-20 18:10:36 -05:00
Clint Branham f3b06171b2 fix: add -TimeoutSeconds for long-running HTTP calls
PveHttpClient was constructed without setting HttpClient.Timeout, so
.NET's 100s default applied to every request. Multi-GB ISO uploads via
Send-PveFile on a real LAN reliably tripped this with TaskCanceledException
after 100 seconds, and there was no way to override it.

- PveSession gains a Timeout (TimeSpan) property, defaulting to 100s.
- PveHttpClient accepts an optional per-instance timeout override that
  takes precedence over the session timeout.
- Connect-PveServer exposes -TimeoutSeconds to set the session default.
- Send-PveFile and Invoke-PveStorageDownload expose -TimeoutSeconds with
  a 30-minute implicit default so large uploads/downloads do not trip
  the 100s default. -TimeoutSeconds 0 means Timeout.InfiniteTimeSpan.

Tracked as F087. Closes #59.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:08:26 -05:00
Clint Branham fa361a3691 fix: address PR #60 review feedback
- SizeParser: wrap TB-suffix overflow in try/catch so callers get
  ArgumentException with the parameter name rather than OverflowException.
- New-PveVm/New-PveContainer: validate -DiskSize/-RootFsSize before
  ShouldProcess so typos like "512M" are rejected even with -WhatIf and
  even when the matching -DiskStorage/-RootFsStorage is omitted.
- Add Pester tests for the new DiskSize and RootFsSize validation paths,
  including a new New-PveContainer.Tests.ps1.
- Add SizeParserTests coverage for the TB overflow path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:06:13 -05:00
Clint Branham 6181c8ce77 fix: normalize -DiskSize and -RootFsSize before sending to PVE
Disk and rootfs size strings were interpolated directly into the disk
spec as "<storage>:<size>", so "60G" produced "local-lvm:60G". On
LVM/LVM-thin storages PVE parses the value after the colon as a volume
name unless it is a bare integer, returning "unable to parse lvm volume
name '60G'". File-backed storages mask this by accepting either form.

SizeParser.NormalizeToGibibytes() now strips G/GB/T/TB suffixes and
returns a bare GiB integer string, so the documented "32G" call shape
works on every storage type. Sub-GB units are rejected with a clear
error rather than being silently truncated.

Tracked as F086. Closes #58.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:59:21 -05:00
GoodOlClint f2925ba49f Merge pull request #57 from GoodOlClint/dependabot/nuget/src/PSProxmoxVE.Core/main/SharpCompress-0.48.1
Bump SharpCompress from 0.47.4 to 0.48.1
2026-05-19 14:20:37 -05:00
dependabot[bot] 9a9830f2e1 Bump SharpCompress from 0.47.4 to 0.48.1
---
updated-dependencies:
- dependency-name: SharpCompress
  dependency-version: 0.48.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-19 15:08:29 +00:00
GoodOlClint 4b0ddf566a Merge pull request #56 from GoodOlClint/dependabot/nuget/tests/PSProxmoxVE.Core.Tests/main/coverlet.collector-10.0.1
Bump coverlet.collector from 8.0.1 to 10.0.1
2026-05-19 10:02:10 -05:00
dependabot[bot] e1bb0d0268 Bump coverlet.collector from 8.0.1 to 10.0.1
---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-version: 10.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-19 14:52:38 +00:00
GoodOlClint 46c4ee3713 Merge pull request #54 from GoodOlClint/dependabot/nuget/tests/PSProxmoxVE.Core.Tests/main/Microsoft.NET.Test.Sdk-18.5.1
Bump Microsoft.NET.Test.Sdk from 18.4.0 to 18.5.1
2026-05-19 09:49:47 -05:00
dependabot[bot] 7219133050 Bump Microsoft.NET.Test.Sdk from 18.4.0 to 18.5.1
---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-04 16:02:50 +00:00
GoodOlClint af4ef8402d Merge pull request #50 from GoodOlClint/dependabot/nuget/tests/PSProxmoxVE.Core.Tests/main/Microsoft.NET.Test.Sdk-18.4.0
Bump Microsoft.NET.Test.Sdk from 18.3.0 to 18.4.0
2026-04-13 09:21:58 -05:00
GoodOlClint 9bf7b2d922 Merge branch 'main' into dependabot/nuget/tests/PSProxmoxVE.Core.Tests/main/Microsoft.NET.Test.Sdk-18.4.0 2026-04-13 09:20:01 -05:00
GoodOlClint a77d2b2062 Merge pull request #48 from GoodOlClint/dependabot/nuget/src/PSProxmoxVE.Core/main/SharpCompress-0.47.4
Bump SharpCompress from 0.47.3 to 0.47.4
2026-04-13 09:19:27 -05:00
GoodOlClint 7dc39646ae Merge branch 'main' into dependabot/nuget/src/PSProxmoxVE.Core/main/SharpCompress-0.47.4 2026-04-13 09:17:59 -05:00
GoodOlClint 6664861ca9 Merge pull request #49 from GoodOlClint/dependabot/github_actions/main/softprops/action-gh-release-3
chore(deps): Bump softprops/action-gh-release from 2 to 3
2026-04-13 09:15:00 -05:00
dependabot[bot] 97ff7701da Bump SharpCompress from 0.47.3 to 0.47.4
---
updated-dependencies:
- dependency-name: SharpCompress
  dependency-version: 0.47.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 14:14:39 +00:00
dependabot[bot] 23ffc3531f chore(deps): Bump softprops/action-gh-release from 2 to 3
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 14:12:00 +00:00
GoodOlClint 2a809b0374 Merge pull request #52 from GoodOlClint/fix/claude-review-post-comments
fix: post Claude Code Review findings as PR comments
2026-04-13 09:10:59 -05:00
Clint Branham 6e2f25a083 fix: rewrite Claude Code Review workflow to match official examples
Previous approach (/code-review:code-review --comment) was based on
incorrect documentation research. Reviewing the actual official
examples at anthropics/claude-code-action/examples/pr-review-*.yml
reveals the correct pattern:

1. Use a custom prompt with explicit review instructions (not a
   plugin slash command)
2. Use claude_args with --allowedTools to enable the MCP inline
   comment tool and gh pr CLI commands — this is what lets Claude
   actually post to the PR
3. Enable track_progress: true for visual progress tracking

Without --allowedTools, Claude has no way to post anything because
the tools for PR commenting aren't allowed by default.

Also removed the plugins and plugin_marketplaces inputs since
they're not needed — the review runs via prompt instructions and
the allowed tools alone.

The custom prompt is tailored to PSProxmoxVE with focus areas
specific to the module: DECISIONS.md compliance, cmdlet
conventions, API correctness against the PVE OpenAPI spec,
test coverage, and security.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:09:54 -05:00
dependabot[bot] aca5ff238b Bump Microsoft.NET.Test.Sdk from 18.3.0 to 18.4.0
---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-13 13:56:51 +00:00
GoodOlClint ac901dbc1b Merge pull request #51 from GoodOlClint/fix/claude-review-allow-dependabot
fix: allow dependabot PRs in Claude Code Review
2026-04-13 08:53:38 -05:00
Clint Branham 2aa2d5994e fix: allow dependabot PRs in Claude Code Review action
Dependabot PRs were being rejected with:
  Workflow initiated by non-human actor: dependabot (type: Bot)

Add allowed_bots: 'dependabot[bot]' to permit dependency update reviews.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 08:52:36 -05:00
GoodOlClint 007f116cea Merge pull request #47 from GoodOlClint/release/v0.1.2
chore: bump version to 0.1.2
v0.1.2
2026-03-27 11:13:28 -05:00
Clint Branham d3953c8c96 chore: bump version to 0.1.2
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:00:02 -05:00
GoodOlClint 69e3b0b15a Merge pull request #46 from GoodOlClint/fix/issues-43-44-45
fix: resolve issues #43, #44, #45
2026-03-27 10:36:40 -05:00
Clint Branham 5dcbde45a6 fix: resolve issues #43, #44, #45
#44 Get-PveApiToken FullTokenId empty:
  - Make FullTokenId a computed property (UserId + "!" + TokenId)
  - RawFullTokenId captures the API's "full-tokenid" for creation responses

#43 Set-PvePermission token ACLs:
  - Add "token" to Type ValidateSet
  - Auto-detect tokens from "!" in UgId (user@realm!tokenid format)
  - Add tokens parameter to UserService.SetPermission

#45 Connect-PveServer return session by default:
  - Always output session (matches Connect-AzAccount pattern)
  - Add -Quiet switch to suppress output
  - Keep -PassThru as hidden deprecated param for backwards compat

Closes #43, closes #44, closes #45

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:22:37 -05:00
GoodOlClint aaff8ed42e Merge pull request #42 from GoodOlClint/release/v0.1.1-preview
chore: bump version to 0.1.1-preview
v0.1.1
2026-03-26 16:54:52 -05:00
Clint Branham 6e953c1cd7 chore: bump version to 0.1.1 (stable release)
Remove prerelease tag — this is now a stable release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 16:49:04 -05:00
GoodOlClint 1694d7f693 Merge pull request #41 from GoodOlClint/fix/validate-api-enums-against-openapi
fix: validate API enum values against PVE OpenAPI spec
2026-03-26 16:33:58 -05:00
Clint Branham 7802b853d4 test: version-aware OpenAPI spec validation (PVE 7/8/9)
Replace single-version fixture with per-version specs from pve-api.
Tests now validate enum values against PVE 7 (best-effort), 8, and 9.

Key findings from version-specific specs:
- VM.Monitor: valid in PVE 7+8, removed in PVE 9
- VM.Replicate: added in PVE 9 only
- VM.GuestAgent.*: added in PVE 9 only
- Mapping.*: added in PVE 8+
- glusterfs: not in any version (removed before PVE 7)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 16:26:19 -05:00
Clint Branham d81c850b0b fix: validate API enum values against PVE OpenAPI spec
Add 70 xUnit tests that validate every ValidateSet in the module
against the PVE OpenAPI spec. Three bugs found and fixed:

- Storage: remove `glusterfs` (dropped in PVE 9), add `btrfs`, `esxi`
- Backup compression: `none` → `0` (PVE uses "0" not "none")
- Cluster resources: remove `lxc` filter (PVE uses `vm` for both)

The pve-api-enums.json fixture (199KB) is extracted from the full
OpenAPI spec and contains parameter enum values for 302 API paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:34:56 -05:00
GoodOlClint 5ceb2469c4 Merge pull request #40 from GoodOlClint/fix/publish-module-path
fix: publish workflow module path must match module name
v0.1.0-preview
2026-03-26 09:24:38 -05:00
Clint Branham 1f09ae6e94 fix: publish workflow module path must match module name
Publish-Module -Path requires the directory name to match the module
name. Changed artifact download path from ./publish/netstandard2.0/
to ./publish/PSProxmoxVE/ so Publish-Module can find the manifest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:19:41 -05:00
GoodOlClint c92fb42d64 Merge pull request #39 from GoodOlClint/fix/ha-rule-type-test
chore: scan-9 review + publish secret fix
2026-03-26 09:13:26 -05:00
Clint Branham 13e0c7bdb1 fix: grant write permissions to Claude Code workflows
- claude-code-review.yml: pull-requests/issues read → write (post reviews)
- claude.yml: contents/pull-requests/issues read → write (respond to @claude)
- Upgrade checkout@v4 → v6, fetch-depth: 1 → 0 for full diff context
- Skip draft PRs in review workflow
- Remove boilerplate comments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:11:54 -05:00
GoodOlClint 0cc493a561 Merge branch 'main' into fix/ha-rule-type-test 2026-03-26 08:59:28 -05:00
Clint Branham 197e206123 chore: scan-9 review findings + fix publish secret name
- Resolve F039 (bare catch regression), F053 (HA coverage), F060
  (cluster config coverage), F084 (PveSession secret hiding)
- Update findings.json: 11 open → 7 open, 0 regressions
- Update REVIEW_REPORT.md with scan-9 results
- Fix publish.yml to use NUGET_API_KEY secret (matches other projects)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:58:35 -05:00
GoodOlClint 008b6b67d3 Merge pull request #38 from GoodOlClint/fix/ha-rule-type-test
fix: remove ValidateSet assertion from Set-PveHaRule Type test
2026-03-26 08:22:22 -05:00
Clint Branham 12ca01cd09 fix: remove ValidateSet assertion from Set-PveHaRule Type test
The ValidateSet attribute was intentionally removed from the Type
parameter during merge review to allow future rule types without
code changes. Updated test to only assert Type is mandatory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:18:47 -05:00
GoodOlClint d37569533d Merge pull request #36 from GoodOlClint/test/cluster-ha-tests 2026-03-25 19:51:55 -05:00
GoodOlClint 4ceb976136 Merge pull request #37 from GoodOlClint/copilot/sub-pr-36 2026-03-25 19:50:20 -05:00
copilot-swe-agent[bot] b1f93e655a fix: set task.Node from UPID + expand SetPveHaRule Type + extract GetNodeFromUpid helper
Co-authored-by: GoodOlClint <151449+GoodOlClint@users.noreply.github.com>
Agent-Logs-Url: https://github.com/GoodOlClint/PSProxmoxVE/sessions/42467843-de5e-4603-99e3-fb182eaf4251
2026-03-26 00:26:00 +00:00
copilot-swe-agent[bot] a9f6360fd2 Initial plan 2026-03-26 00:20:03 +00:00
Clint Branham 514ce3fc1b fix: Set-PveHaRule requires mandatory Type parameter
PVE 9 API requires 'type' on PUT /cluster/ha/rules/{rule} even for
updates. Added mandatory Type parameter with ValidateSet for
node-affinity and resource-affinity.

Updated integration test and Pester unit tests to pass -Type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:52:23 -05:00
Clint Branham d43387806e refactor: adapt cluster tests to _IntegrationHelper + rename to 16_Cluster
- Rename ZZ.ClusterConfig.Integration.Tests.ps1 → 16_Cluster.Tests.ps1
- Replace manual env var setup with _IntegrationHelper.ps1 + Connect-TestPve
- Use credential auth (root@pam) throughout — no API tokens
- Use $script:PasswordB for node B auth (from helper)
- Access JoinInfo.Nodelist as List<Dictionary> (native types from D013)
- Keep cluster-specific skip helpers (Skip-IfNoCluster, Skip-IfPve9HaGroups)
- Remove redundant Connection context (Connect-TestPve handles it)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:40:01 -05:00
Clint Branham e7b1c8488c fix: HA rule test creates real VM + HA resource before rule
PVE 9 rejects rules referencing unmanaged resources. Test now creates
a minimal VM, registers it as a disabled HA resource, then creates
the node-affinity rule. Cleanup removes rule, resource, and VM.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:40:01 -05:00
Clint Branham 9636c45a40 fix: remove unsupported affinity param from HA rule test
PVE 9 rejects 'affinity' as an unexpected property on POST
cluster/ha/rules — it's implied by the node-affinity type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:40:01 -05:00
Clint Branham fc29d01a7a test: add HA rules CRUD integration tests for PVE 9.0+
Full lifecycle: create node-affinity rule, list, get by ID, update
comment, delete, and verify deletion. Uses vm:99999 as a synthetic
resource SID. Tests skip on PVE 8 (rules not available).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:40:01 -05:00