mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-07-26 07:58:14 +00:00
fix: address PR #69 review feedback
- VmService.ExecuteGuestCommand: guard against null elements in -Args. The old JSON-serialization tolerated nulls (as "null"); the repeated-key path would NRE in EncodeFormValue. Throw a clear ArgumentException instead. - findings.json: refresh the stale counters block (untouched since F085) to the actual ledger state — next_id 92, resolved 83 — and bump last_updated to 2026-05-22. last_scan_date stays 2026-03-26 (F086–F091 came from issue triage, not a formal review scan). - VmServiceTests: add empty-array (single command entry) and null-element (throws) cases. Note: F091 is the correct next ID — F086–F090 already exist from prior merged PRs (#60/#61/#66/#67); only the counters were lagging. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"_schema_version": "1.0",
|
"_schema_version": "1.0",
|
||||||
"_description": "PSProxmoxVE stable findings ledger. IDs are permanent (F001, F002...). Resolved findings are never deleted — they are marked resolved with evidence. If a finding reappears, it is marked regressed and retains its original ID.",
|
"_description": "PSProxmoxVE stable findings ledger. IDs are permanent (F001, F002...). Resolved findings are never deleted — they are marked resolved with evidence. If a finding reappears, it is marked regressed and retains its original ID.",
|
||||||
"last_updated": "2026-03-26",
|
"last_updated": "2026-05-22",
|
||||||
"last_scan_date": "2026-03-26",
|
"last_scan_date": "2026-03-26",
|
||||||
"counters": {
|
"counters": {
|
||||||
"next_id": 86,
|
"next_id": 92,
|
||||||
"total_open": 7,
|
"total_open": 7,
|
||||||
"total_resolved": 77,
|
"total_resolved": 83,
|
||||||
"total_regressed": 0,
|
"total_regressed": 0,
|
||||||
"open": 7,
|
"open": 7,
|
||||||
"resolved": 77,
|
"resolved": 83,
|
||||||
"regressed": 0,
|
"regressed": 0,
|
||||||
"wont_fix": 1
|
"wont_fix": 1
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -610,7 +610,11 @@ namespace PSProxmoxVE.Core.Services
|
|||||||
if (args != null)
|
if (args != null)
|
||||||
{
|
{
|
||||||
foreach (var arg in args)
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
if (arg == null)
|
||||||
|
throw new ArgumentException("Args elements must not be null.", nameof(args));
|
||||||
data.Add(new KeyValuePair<string, string>("command", arg));
|
data.Add(new KeyValuePair<string, string>("command", arg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/agent/exec", data)
|
var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/agent/exec", data)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -77,5 +78,36 @@ namespace PSProxmoxVE.Core.Tests.Services
|
|||||||
Assert.Equal("command", only.Key);
|
Assert.Equal("command", only.Key);
|
||||||
Assert.Equal("whoami", only.Value);
|
Assert.Equal("whoami", only.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExecuteGuestCommand_EmptyArgs_SendsSingleCommandEntry()
|
||||||
|
{
|
||||||
|
List<KeyValuePair<string, string>>? captured = null;
|
||||||
|
var mockClient = new Mock<IPveHttpClient>();
|
||||||
|
mockClient
|
||||||
|
.Setup(c => c.PostAsync(It.IsAny<string>(), It.IsAny<IEnumerable<KeyValuePair<string, string>>>()))
|
||||||
|
.Callback<string, IEnumerable<KeyValuePair<string, string>>>((_, data) => captured = data.ToList())
|
||||||
|
.ReturnsAsync("{\"data\":{\"pid\":9}}");
|
||||||
|
|
||||||
|
var service = new VmService(mockClient.Object);
|
||||||
|
service.ExecuteGuestCommand(CreateSession(), TestNode, TestVmId, "whoami", new string[0]);
|
||||||
|
|
||||||
|
Assert.NotNull(captured);
|
||||||
|
var only = Assert.Single(captured!);
|
||||||
|
Assert.Equal("command", only.Key);
|
||||||
|
Assert.Equal("whoami", only.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExecuteGuestCommand_NullArgElement_ThrowsArgumentException()
|
||||||
|
{
|
||||||
|
var mockClient = new Mock<IPveHttpClient>();
|
||||||
|
var service = new VmService(mockClient.Object);
|
||||||
|
|
||||||
|
var ex = Assert.Throws<ArgumentException>(() =>
|
||||||
|
service.ExecuteGuestCommand(CreateSession(), TestNode, TestVmId,
|
||||||
|
"cmd.exe", new[] { "/c", null!, "echo" }));
|
||||||
|
Assert.Equal("args", ex.ParamName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user