mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-09-04 03:05:32 +00:00
test: assert node B joined by name, not an online-node count
Closes #94
This commit is contained in:
committed by
GitHub
parent
f96511bbe0
commit
959b62c86f
@@ -27,6 +27,23 @@ git push -u origin feat/my-feature
|
||||
gh pr create
|
||||
```
|
||||
|
||||
### Agent pushes go through the GitHub MCP (operator decision 2026-09-01)
|
||||
|
||||
Agent-authored branches are pushed with the `github` MCP tools (`create_branch` +
|
||||
`push_files`, committing as the `goodolclint-claude` App), not local `git push` over the
|
||||
operator's SSH key. Local git stays for everything else — branches, commits, diffs; only
|
||||
the push goes through the API. `push_files` creates its own commit from full file
|
||||
contents, so the commit message is passed to the tool and no `Co-Authored-By` trailer is
|
||||
needed.
|
||||
|
||||
Every API push is byte-verified before the PR: commit the identical change locally,
|
||||
`git fetch`, and `git diff <local-commit> origin/<branch> --` must be empty. `push_files`
|
||||
cannot express a removal — use `delete_file` for deletions, and a rename is `push_files`
|
||||
of the new path plus `delete_file` of the old.
|
||||
|
||||
**Exception: `.github/workflows/*`.** The App token has no `workflows` permission, so
|
||||
GitHub refuses those pushes; they stay on operator-attended local `git push`.
|
||||
|
||||
### Dev container (recommended)
|
||||
|
||||
A Docker-based dev environment replicates the full CI setup locally. Works on ARM Macs
|
||||
|
||||
@@ -204,9 +204,13 @@ Describe 'Cluster Config & HA Lifecycle — Integration' -Tag 'Integration' {
|
||||
$script:NodeBName | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Get-PveClusterStatus shows 2 nodes online' {
|
||||
It 'Get-PveClusterStatus shows node B online by name' {
|
||||
if (Skip-IfNoNodeB) { return }
|
||||
if (Skip-IfNoCluster) { return }
|
||||
if (-not $script:NodeBName) {
|
||||
Set-ItResult -Skipped -Because 'Node B name was not discovered'
|
||||
return
|
||||
}
|
||||
|
||||
# Corosync membership reaches the status endpoint seconds after
|
||||
# the join task completes — poll rather than assert instantly.
|
||||
@@ -214,8 +218,8 @@ Describe 'Cluster Config & HA Lifecycle — Integration' -Tag 'Integration' {
|
||||
do {
|
||||
$status = Get-PveClusterStatus -ErrorAction Stop
|
||||
$nodeEntries = @($status) | Where-Object { $_.Type -eq 'node' }
|
||||
$onlineNodes = @($nodeEntries) | Where-Object { $_.Online -eq 1 }
|
||||
if (@($onlineNodes).Count -ge 2) { break }
|
||||
$nodeB = @($nodeEntries) | Where-Object { $_.Name -eq $script:NodeBName } | Select-Object -First 1
|
||||
if ($nodeB -and $nodeB.Online -eq 1) { break }
|
||||
Start-Sleep -Seconds 3
|
||||
} while ([DateTime]::UtcNow -lt $deadline)
|
||||
|
||||
@@ -225,8 +229,45 @@ Describe 'Cluster Config & HA Lifecycle — Integration' -Tag 'Integration' {
|
||||
Write-Host " node=$($n.Name) nodeid=$($n.NodeId) ring0=$($n.Ip) online=$($n.Online) local=$($n.Local)"
|
||||
}
|
||||
|
||||
@($nodeEntries).Count | Should -BeGreaterOrEqual 2
|
||||
@($onlineNodes).Count | Should -BeGreaterOrEqual 2
|
||||
$nodeB | Should -Not -BeNullOrEmpty -Because "node A's cluster status should list $($script:NodeBName)"
|
||||
$nodeB.Online | Should -Be 1 -Because "node A should see $($script:NodeBName) online"
|
||||
}
|
||||
|
||||
It 'Node B reports itself as part of the cluster' {
|
||||
if (Skip-IfNoNodeB) { return }
|
||||
if (Skip-IfNoCluster) { return }
|
||||
if (-not $script:NodeBName) {
|
||||
Set-ItResult -Skipped -Because 'Node B name was not discovered'
|
||||
return
|
||||
}
|
||||
|
||||
# Node A seeing node B is not the same claim as node B believing it
|
||||
# joined: in the #93 failure node B's pmxcfs stayed in local mode and
|
||||
# reported online=0 while corosync membership looked healthy.
|
||||
$secPw = ConvertTo-SecureString $script:PasswordB -AsPlainText -Force
|
||||
$credB = New-Object System.Management.Automation.PSCredential('root@pam', $secPw)
|
||||
Connect-PveServer `
|
||||
-Server $script:HostB `
|
||||
-Port $script:Port `
|
||||
-Credential $credB `
|
||||
-SkipCertificateCheck
|
||||
|
||||
try {
|
||||
$statusB = Get-PveClusterStatus -ErrorAction Stop
|
||||
$clusterB = @($statusB) | Where-Object { $_.Type -eq 'cluster' } | Select-Object -First 1
|
||||
$selfB = @($statusB) |
|
||||
Where-Object { $_.Type -eq 'node' -and $_.Name -eq $script:NodeBName } |
|
||||
Select-Object -First 1
|
||||
|
||||
Write-Host "node B's own view: cluster=$($clusterB.Name) quorate=$($clusterB.Quorate) self-online=$($selfB.Online) self-local=$($selfB.Local)"
|
||||
|
||||
$clusterB | Should -Not -BeNullOrEmpty -Because "$($script:NodeBName) should report a cluster entry, not local mode"
|
||||
$selfB | Should -Not -BeNullOrEmpty -Because "$($script:NodeBName) should list itself as a cluster node"
|
||||
$selfB.Online | Should -Be 1 -Because "$($script:NodeBName) should consider itself online in the cluster"
|
||||
}
|
||||
finally {
|
||||
Connect-TestPve
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user