mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 02:28:59 +00:00
Fix multi-organization Proxmox connection identity
This commit is contained in:
parent
8e5ef365d4
commit
d1ee6e928b
17 changed files with 251 additions and 86 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
6.2.0-rc.2
|
||||
6.2.0-rc.3
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ apiVersion: v2
|
|||
name: pulse
|
||||
description: Helm chart for deploying the Pulse hub and optional Docker monitoring agent.
|
||||
type: application
|
||||
version: 6.2.0-rc.2
|
||||
appVersion: "6.2.0-rc.2"
|
||||
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.2.0-rc.2/docs/images/pulse-logo.svg
|
||||
version: 6.2.0-rc.3
|
||||
appVersion: "6.2.0-rc.3"
|
||||
icon: https://raw.githubusercontent.com/rcourtman/Pulse/v6.2.0-rc.3/docs/images/pulse-logo.svg
|
||||
keywords:
|
||||
- monitoring
|
||||
- proxmox
|
||||
|
|
@ -32,7 +32,7 @@ annotations:
|
|||
description: Smoke tests with kind cluster deployment
|
||||
artifacthub.io/links: |
|
||||
- name: Documentation
|
||||
url: https://github.com/rcourtman/Pulse/blob/v6.2.0-rc.2/docs/KUBERNETES.md
|
||||
url: https://github.com/rcourtman/Pulse/blob/v6.2.0-rc.3/docs/KUBERNETES.md
|
||||
- name: Support
|
||||
url: https://github.com/rcourtman/Pulse/discussions
|
||||
artifacthub.io/maintainers: |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# pulse
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
Helm chart for deploying the Pulse hub and optional Docker monitoring agent.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ version: '3.8'
|
|||
|
||||
services:
|
||||
pulse:
|
||||
image: ${PULSE_IMAGE:-rcourtman/pulse:6.2.0-rc.2}
|
||||
image: ${PULSE_IMAGE:-rcourtman/pulse:6.2.0-rc.3}
|
||||
container_name: pulse
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ For historical v4 notes that previously lived in this repo, see:
|
|||
`docs/releases/RELEASE_NOTES_v4.md`
|
||||
|
||||
For the current v6 support release candidate packet, see:
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.2.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.2.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.3.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.3.md`
|
||||
|
||||
For historical v6.2 support release candidate packets, see:
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.2.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.2.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.1.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.1.md`
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ This guide covers practical upgrade steps for existing Pulse installs moving to
|
|||
|
||||
For the current v6 support release candidate packet, see:
|
||||
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.2.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.2.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.3.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.3.md`
|
||||
|
||||
For historical v6.2 support release candidate packets, see:
|
||||
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.2.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.2.md`
|
||||
- `docs/releases/RELEASE_NOTES_v6.2.0-rc.1.md`
|
||||
- `docs/releases/V6_CHANGELOG_v6.2.0-rc.1.md`
|
||||
|
||||
|
|
|
|||
|
|
@ -9229,13 +9229,13 @@
|
|||
],
|
||||
"work_claims": [
|
||||
{
|
||||
"id": "release-operator-v620rc2-release-gate-single-build-release-promotion-path",
|
||||
"agent_id": "release-operator-v620rc2",
|
||||
"summary": "Prepare and publish v6.2.0-rc.2 through the governed exact-SHA promotion workflow",
|
||||
"id": "release-operator-v620rc3-release-gate-single-build-release-promotion-path",
|
||||
"agent_id": "release-operator-v620rc3",
|
||||
"summary": "Prepare and publish v6.2.0-rc.3 through the governed exact-SHA promotion workflow",
|
||||
"target_id": "v6-product-lane-expansion",
|
||||
"claimed_at": "2026-07-28T14:59:51Z",
|
||||
"heartbeat_at": "2026-07-28T14:59:51Z",
|
||||
"expires_at": "2026-07-28T22:59:51Z",
|
||||
"claimed_at": "2026-07-28T16:07:39Z",
|
||||
"heartbeat_at": "2026-07-28T16:07:39Z",
|
||||
"expires_at": "2026-07-29T00:07:39Z",
|
||||
"work_item": {
|
||||
"kind": "release-gate",
|
||||
"id": "single-build-release-promotion-path"
|
||||
|
|
|
|||
|
|
@ -1136,29 +1136,30 @@ host-local redirect contract as runtime token minting and exchange. Proof input
|
|||
must reject absolute, scheme-relative, backslash-authority, encoded-separator,
|
||||
and control-character targets before constructing the handoff request.
|
||||
|
||||
The active support prerelease `v6.2.0-rc.2` cut sets the repo-root `VERSION`,
|
||||
The active support prerelease `v6.2.0-rc.3` cut sets the repo-root `VERSION`,
|
||||
repo-root `docker-compose.yml` image default, `scripts/install-docker.sh`
|
||||
fallback, and Helm chart release metadata to the same `6.2.0-rc.2` release
|
||||
fallback, and Helm chart release metadata to the same `6.2.0-rc.3` release
|
||||
version. This support prerelease keeps `rollback_version=v6.1.2`, publishes a
|
||||
versioned public GitHub prerelease plus versioned Docker and Helm artifacts, and
|
||||
does not move stable/latest install pointers or stable semver aliases. Stable
|
||||
install pointers stay on `v6.1.2`, whose active stable cut is recorded below and
|
||||
continues to govern the stable line until this candidate is promoted. The second
|
||||
`v6.2.0` candidate is a hardening and bugfix cut that supersedes `v6.2.0-rc.1`
|
||||
without dropping anything it carried: it restores unattended-update reliability
|
||||
including in-place repair of already-deployed update units, corrects PBS backup
|
||||
attribution across multiple Proxmox clusters, repairs Proxmox installer
|
||||
registration including per-canonical-type bootstrap grants on combined hosts,
|
||||
hardens the Patrol readiness streaming transport and gates readiness on a
|
||||
completed verdict, ends discovery-policy DNS and SSH retry churn, adds explicit
|
||||
per-metric threshold off toggles, derives SSO callback URLs from the request
|
||||
that reached Pulse, and documents Entra ID SSO integration. The exact `main` SHA
|
||||
must pass the integrated release checks and immutable-candidate build before the
|
||||
single-build workflow crosses its public mutation boundary.
|
||||
The `v6.2.0-rc.2` server cut is classified `no-mobile-impact`; no companion
|
||||
continues to govern the stable line until this candidate is promoted. The third
|
||||
`v6.2.0` candidate is a focused support correction that supersedes
|
||||
`v6.2.0-rc.2`: adding a Proxmox connection now applies the same endpoint and
|
||||
TLS identity doctrine as later configuration consolidation, so clusters in
|
||||
different organizations are not merged merely because their internal names,
|
||||
node names, and private addresses overlap. The exact `main` SHA must pass the
|
||||
integrated release checks and immutable-candidate build before the single-build
|
||||
workflow crosses its public mutation boundary.
|
||||
The `v6.2.0-rc.3` server cut is classified `no-mobile-impact`; no companion
|
||||
build upload is part of this cut. The existing mobile candidate programme
|
||||
remains separate, and the release packet must not describe a public store
|
||||
rollout.
|
||||
The preceding `v6.2.0-rc.2` candidate used the same support-prerelease path
|
||||
with `rollback_version=v6.1.2` and pinned the same four install surfaces to
|
||||
`6.2.0-rc.2`. It is superseded by this cut and no longer governs the install
|
||||
pins; its packet stays in `docs/releases/` as the historical candidate record
|
||||
for the `v6.2.0` line.
|
||||
The preceding `v6.2.0-rc.1` candidate used the same support-prerelease path
|
||||
with `rollback_version=v6.1.2` and pinned the same four install surfaces to
|
||||
`6.2.0-rc.1`. It is superseded by this cut and no longer governs the install
|
||||
|
|
@ -1313,14 +1314,14 @@ For the active stable `v6.1.2` cut, the repo-root compose default and
|
|||
`scripts/install-docker.sh` fallback must both pin `6.1.2` whenever the
|
||||
governed `VERSION` is that stable cut. The stable promotion guard remains in
|
||||
force and rejects leftover `-rc.` defaults.
|
||||
For the active support prerelease `v6.2.0-rc.2` cut, the repo-root compose
|
||||
default and `scripts/install-docker.sh` fallback must both pin `6.2.0-rc.2`
|
||||
For the active support prerelease `v6.2.0-rc.3` cut, the repo-root compose
|
||||
default and `scripts/install-docker.sh` fallback must both pin `6.2.0-rc.3`
|
||||
until the next governed stable cut moves them forward. The stable promotion
|
||||
guard remains in force and must reject leftover `-rc.` defaults when the
|
||||
governed `VERSION` returns to a stable release. Each new candidate on the
|
||||
`v6.2.0` line moves these two pins together with the repo-root `VERSION` and
|
||||
the Helm chart metadata in the same commit; a candidate that leaves any of the
|
||||
four on the superseded `6.2.0-rc.1` value is a release-packet blocker.
|
||||
four on a superseded `6.2.0-rc.*` value is a release-packet blocker.
|
||||
The RC7 packet refresh records `fc10de9b5477613316473267b72b05b6b2b7aaff`
|
||||
as the current validation-risk commit. That head includes the earlier
|
||||
Docker-default correction plus the follow-on capacity-forecast and Patrol
|
||||
|
|
|
|||
50
docs/releases/RELEASE_NOTES_v6.2.0-rc.3.md
Normal file
50
docs/releases/RELEASE_NOTES_v6.2.0-rc.3.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Pulse v6.2.0-rc.3 Release Notes
|
||||
|
||||
`v6.2.0-rc.3` is a release candidate for the next Pulse v6 minor line. It
|
||||
follows stable `v6.1.2` and supersedes `v6.2.0-rc.2`. This focused support
|
||||
candidate corrects the remaining multi-organization Proxmox connection
|
||||
collision reported against the first two candidates.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Proxmox clusters in different organizations stay separate even when they
|
||||
reuse the same internal Proxmox cluster name, node names, and private IP
|
||||
addresses.
|
||||
- Captured TLS certificate fingerprints now govern the add-connection path,
|
||||
using the same identity decision as configuration consolidation.
|
||||
|
||||
## Fixed
|
||||
|
||||
- The Proxmox add-connection handler no longer merges a newly discovered
|
||||
cluster into an existing connection solely because their internal cluster
|
||||
names match.
|
||||
- A contradictory TLS fingerprint vetoes the merge before either connection
|
||||
can be removed from saved configuration.
|
||||
- Legitimate duplicate connections to the same physical cluster still merge
|
||||
when their cluster name, endpoint evidence, and TLS identity agree.
|
||||
|
||||
## Upgrade Notes
|
||||
|
||||
Use the normal v6 install or update flow for `v6.2.0-rc.3` only when you are
|
||||
comfortable testing an RC. The rollback target is `v6.1.2`.
|
||||
|
||||
The exact rollback reinstall command is:
|
||||
|
||||
```bash
|
||||
./scripts/install.sh --version v6.1.2
|
||||
```
|
||||
|
||||
After updating, a cluster that returned to Network Discovery can be connected
|
||||
again. Existing healthy connections do not need to be removed first.
|
||||
|
||||
This server candidate has no mobile compatibility change and does not require a
|
||||
companion build upload. No public mobile-store rollout is part of this RC.
|
||||
|
||||
Windows Unified Agent binaries in this candidate keep checksum and
|
||||
detached-signature verification, but they are not yet Authenticode-signed and
|
||||
Windows may show an unknown-publisher warning. No unsigned-Windows exception
|
||||
applies to any `v6.2.0` release. Stable `v6.2.0` must publish Windows agents
|
||||
through the mandatory SignPath Authenticode path.
|
||||
|
||||
Paid Pulse Pro, Relay, and eligible legacy customers should continue to use the
|
||||
private download page and private runtime image for paid runtime features.
|
||||
30
docs/releases/V6_CHANGELOG_v6.2.0-rc.3.md
Normal file
30
docs/releases/V6_CHANGELOG_v6.2.0-rc.3.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Pulse v6.2.0-rc.3
|
||||
|
||||
_This changelog describes the changes since `v6.2.0-rc.2`.
|
||||
`v6.2.0-rc.3` remains a prerelease and rolls back to stable `v6.1.2`._
|
||||
|
||||
## Fixed
|
||||
|
||||
- Same-named Proxmox clusters from different organizations remain distinct
|
||||
when overlapping node names and private addresses carry contradicting TLS
|
||||
certificate fingerprints.
|
||||
- The connection add handler now uses the shared identity predicate instead of
|
||||
treating a matching internal cluster name as sufficient proof of identity.
|
||||
- A regression test reproduces the reported sequence where adding `rewo`
|
||||
removed `enacon`, then adding `enacon` removed `rewo`.
|
||||
|
||||
## Release Metadata
|
||||
|
||||
- Version: `v6.2.0-rc.3`
|
||||
- Previous candidate: `v6.2.0-rc.2`
|
||||
- Previous stable: `v6.1.2`
|
||||
- Rollback target: `v6.1.2`
|
||||
- Rollback command: `./scripts/install.sh --version v6.1.2`
|
||||
- Promotion path: exact-SHA single-build release candidate from `main`,
|
||||
published as a support prerelease that does not move stable or latest
|
||||
install pointers
|
||||
- Windows signing decision: Authenticode through SignPath is the mandatory
|
||||
signing backend and no unsigned-Windows exception applies to any `v6.2.0`
|
||||
release
|
||||
- Mobile decision: `no-mobile-impact`; no companion build upload or public
|
||||
store rollout is part of this candidate
|
||||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
|
||||
"github.com/rcourtman/pulse-go-rewrite/pkg/proxmox"
|
||||
)
|
||||
|
||||
func TestHandleAddNode(t *testing.T) {
|
||||
|
|
@ -491,3 +492,64 @@ func TestHandleAddNodeConsolidatesStandaloneOverlapIntoClusterInMemory(t *testin
|
|||
t.Fatalf("expected VerifySSL to be promoted onto the surviving cluster")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleAddNodeKeepsDistinctSameNameClustersWithContradictingFingerprints(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
DataPath: t.TempDir(),
|
||||
PVEInstances: []config.PVEInstance{
|
||||
{
|
||||
Name: "enacon",
|
||||
Host: "https://192.168.1.253:8006",
|
||||
ClusterName: "production",
|
||||
IsCluster: true,
|
||||
ClusterEndpoints: []config.ClusterEndpoint{
|
||||
{
|
||||
NodeName: "pve01",
|
||||
Host: "https://192.168.1.246:8006",
|
||||
IP: "192.168.1.246",
|
||||
Fingerprint: "AA:AA",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
handler := newTestConfigHandlers(t, cfg)
|
||||
|
||||
originalDetect := detectPVECluster
|
||||
t.Cleanup(func() { detectPVECluster = originalDetect })
|
||||
detectPVECluster = func(clientConfig proxmox.ClientConfig, nodeName string, existing []config.ClusterEndpoint) (bool, string, []config.ClusterEndpoint) {
|
||||
return true, "production", []config.ClusterEndpoint{
|
||||
{
|
||||
NodeName: "pve01",
|
||||
Host: "https://192.168.1.246:8006",
|
||||
IP: "192.168.1.246",
|
||||
Fingerprint: "BB:BB",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
body, err := json.Marshal(map[string]any{
|
||||
"name": "rewo",
|
||||
"type": "pve",
|
||||
"host": "192.168.1.254",
|
||||
"tokenName": "pulse@pve!token",
|
||||
"tokenValue": "secret",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/config/nodes", bytes.NewBuffer(body))
|
||||
rec := httptest.NewRecorder()
|
||||
handler.HandleAddNode(rec, req)
|
||||
|
||||
if rec.Code != http.StatusCreated {
|
||||
t.Fatalf("status = %d, want 201: %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if len(cfg.PVEInstances) != 2 {
|
||||
t.Fatalf("PVE instances = %#v, want both organizations to remain configured", cfg.PVEInstances)
|
||||
}
|
||||
if cfg.PVEInstances[0].Name != "enacon" || cfg.PVEInstances[1].Name != "rewo" {
|
||||
t.Fatalf("PVE instance names = %q, %q, want enacon and rewo", cfg.PVEInstances[0].Name, cfg.PVEInstances[1].Name)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -405,15 +405,23 @@ func (h *ConfigHandlers) handleAddNode(w http.ResponseWriter, r *http.Request) {
|
|||
isCluster, clusterName, clusterEndpoints = detectPVECluster(clientConfig, req.Name, nil)
|
||||
}
|
||||
|
||||
// CLUSTER DEDUPLICATION: If this node is part of a cluster, check if we already
|
||||
// have that cluster configured. If so, this is a duplicate - we should merge
|
||||
// the node as an endpoint to the existing cluster instead of creating a new instance.
|
||||
// This prevents duplicate VMs/containers when users install agents on multiple cluster nodes.
|
||||
// CLUSTER DEDUPLICATION: If this node is part of a cluster, merge it
|
||||
// only when endpoint and TLS evidence identify an existing cluster.
|
||||
// Cluster names and private addresses can repeat across organizations.
|
||||
if isCluster && clusterName != "" {
|
||||
candidateCluster := config.PVEInstance{
|
||||
Name: req.Name,
|
||||
Host: host,
|
||||
Fingerprint: req.Fingerprint,
|
||||
IsCluster: true,
|
||||
ClusterName: clusterName,
|
||||
ClusterEndpoints: clusterEndpoints,
|
||||
}
|
||||
for i := range h.getConfig(r.Context()).PVEInstances {
|
||||
existingInstance := &h.getConfig(r.Context()).PVEInstances[i]
|
||||
if existingInstance.IsCluster && existingInstance.ClusterName == clusterName {
|
||||
// Found existing cluster with same name - merge endpoints!
|
||||
if config.PVEClusterInstancesShareIdentity(*existingInstance, candidateCluster) {
|
||||
// Strong identity evidence confirms this is another view
|
||||
// of the existing cluster, so merge its endpoints.
|
||||
log.Info().
|
||||
Str("cluster", clusterName).
|
||||
Str("existingInstance", existingInstance.Name).
|
||||
|
|
|
|||
|
|
@ -125,6 +125,18 @@ func pveClusterInstancesHaveFingerprintConflict(a, b PVEInstance) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// PVEClusterInstancesShareIdentity reports whether two configured cluster
|
||||
// views have enough evidence to be consolidated. Cluster names are not unique
|
||||
// across organizations, so a matching name alone is never sufficient.
|
||||
func PVEClusterInstancesShareIdentity(a, b PVEInstance) bool {
|
||||
return a.IsCluster &&
|
||||
b.IsCluster &&
|
||||
strings.TrimSpace(a.ClusterName) != "" &&
|
||||
strings.EqualFold(strings.TrimSpace(a.ClusterName), strings.TrimSpace(b.ClusterName)) &&
|
||||
!pveClusterInstancesHaveFingerprintConflict(a, b) &&
|
||||
pveClusterInstancesHaveStrongOverlap(a, b)
|
||||
}
|
||||
|
||||
func mergeDuplicateClusterInstances(instances []PVEInstance) ([]PVEInstance, bool) {
|
||||
removed := make(map[int]struct{})
|
||||
mergedAny := false
|
||||
|
|
@ -146,10 +158,7 @@ func mergeDuplicateClusterInstances(instances []PVEInstance) ([]PVEInstance, boo
|
|||
continue
|
||||
}
|
||||
duplicate := instances[dupIdx]
|
||||
if !duplicate.IsCluster ||
|
||||
!strings.EqualFold(strings.TrimSpace(primary.ClusterName), strings.TrimSpace(duplicate.ClusterName)) ||
|
||||
pveClusterInstancesHaveFingerprintConflict(*primary, duplicate) ||
|
||||
!pveClusterInstancesHaveStrongOverlap(*primary, duplicate) {
|
||||
if !PVEClusterInstancesShareIdentity(*primary, duplicate) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -237,6 +237,29 @@ func TestConsolidatePVEInstancesKeepsSameNameClustersWithCollidingPrivateIPs(t *
|
|||
}
|
||||
}
|
||||
|
||||
func TestPVEClusterInstancesShareIdentityRejectsSameNameWithContradictingFingerprints(t *testing.T) {
|
||||
siteA := PVEInstance{
|
||||
Name: "enacon",
|
||||
ClusterName: "production",
|
||||
IsCluster: true,
|
||||
ClusterEndpoints: []ClusterEndpoint{
|
||||
{NodeName: "pve01", Host: "https://192.168.1.246:8006", IP: "192.168.1.246", Fingerprint: "AA:AA"},
|
||||
},
|
||||
}
|
||||
siteB := PVEInstance{
|
||||
Name: "rewo",
|
||||
ClusterName: "production",
|
||||
IsCluster: true,
|
||||
ClusterEndpoints: []ClusterEndpoint{
|
||||
{NodeName: "pve01", Host: "https://192.168.1.246:8006", IP: "192.168.1.246", Fingerprint: "BB:BB"},
|
||||
},
|
||||
}
|
||||
|
||||
if PVEClusterInstancesShareIdentity(siteA, siteB) {
|
||||
t.Fatal("same-name clusters with contradicting TLS fingerprints must not share identity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsolidatePVEInstancesKeepsStandaloneWithContradictingFingerprint(t *testing.T) {
|
||||
// A standalone whose address collides with a cluster endpoint at another
|
||||
// site must not fold into that cluster when its TLS fingerprint disagrees.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ set -euo pipefail
|
|||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||
DOCKER_IMAGE_REPO="${DOCKER_IMAGE_REPO:-rcourtman/pulse}"
|
||||
CANONICAL_DEFAULT_PULSE_VERSION="6.2.0-rc.2"
|
||||
CANONICAL_DEFAULT_PULSE_VERSION="6.2.0-rc.3"
|
||||
|
||||
resolve_default_pulse_version() {
|
||||
if [ -n "${PULSE_IMAGE_VERSION:-}" ]; then
|
||||
|
|
|
|||
|
|
@ -406,27 +406,13 @@ func TestCurrentSupportPrereleasePacketTracksInstallMetadata(t *testing.T) {
|
|||
"`v"+version+"` is a release candidate",
|
||||
"## Highlights",
|
||||
"stable `v"+previous+"`",
|
||||
"supersedes `v6.2.0-rc.1`",
|
||||
"Unattended updates no longer stop Pulse in the night",
|
||||
"the timer now runs once, failures always restart the service",
|
||||
"already-deployed installations repair their own stale update units",
|
||||
"PBS backups are attributed to the right guest on estates with more than one Proxmox cluster",
|
||||
"combined PVE+PBS hosts",
|
||||
"survives reverse proxies with short read timeouts",
|
||||
"never renders a proxy's HTML error page into the results",
|
||||
"now uses the shared DNS cache",
|
||||
"`pulse-update.timer`",
|
||||
"submission-source learner that only trusts evidence when every candidate cluster is visible",
|
||||
"one registration per product type, bound to the first presenting hostname",
|
||||
"streams keepalive bytes from the first moment of the run",
|
||||
"A connection cut mid-run is classified as interrupted",
|
||||
"an interrupted check never blocks Patrol from running",
|
||||
"resolves hostnames through the shared cached resolver",
|
||||
"back off with decay",
|
||||
"explicit On/Off toggle",
|
||||
"never a `localhost` guess that fails at the identity provider",
|
||||
"Microsoft Entra ID (Azure AD) SSO integration guide",
|
||||
"`CAP_NET_RAW`",
|
||||
"supersedes `v6.2.0-rc.2`",
|
||||
"clusters in different organizations stay separate",
|
||||
"internal Proxmox cluster name",
|
||||
"node names, and private IP addresses",
|
||||
"Captured TLS certificate fingerprints",
|
||||
"add-connection path",
|
||||
"same identity decision as configuration consolidation",
|
||||
"no mobile compatibility change",
|
||||
"No public mobile-store rollout",
|
||||
"not yet Authenticode-signed",
|
||||
|
|
@ -435,26 +421,17 @@ func TestCurrentSupportPrereleasePacketTracksInstallMetadata(t *testing.T) {
|
|||
)
|
||||
assertFileContainsAllNormalized(t, changelogPath,
|
||||
"Version: `v"+version+"`",
|
||||
"Previous candidate: `v6.2.0-rc.1`",
|
||||
"Previous candidate: `v6.2.0-rc.2`",
|
||||
"Previous stable: `v"+previous+"`",
|
||||
"Rollback target: `v"+previous+"`",
|
||||
"Promotion path: exact-SHA single-build release candidate from `main`",
|
||||
"This changelog describes the changes since `v6.2.0-rc.1`",
|
||||
"Explicit per-metric off toggles in the per-resource override editor",
|
||||
"OIDC provider cards show the provider's callback / redirect URL with a copy button",
|
||||
"carried two `OnCalendar` lines",
|
||||
"Auto-update asset staging is guarded",
|
||||
"migrate through a transient `systemd-run` unit on the next update cycle",
|
||||
"PBS backup attribution for VMIDs shared across clusters",
|
||||
"one registration per canonical product type",
|
||||
"The Patrol readiness endpoint commits its response header and streams keepalive bytes",
|
||||
"Patrol readiness is reported only from a completed overall verdict",
|
||||
"resolves hostnames through the shared cached resolver",
|
||||
"back off with decay instead of retrying every poll cycle",
|
||||
"LXC memory metrics fall back to the cluster-resources listing",
|
||||
"Agent command execution honors the configuration gate at channel admission",
|
||||
"derived from the configured public URL or, when none is set, from the request that reached Pulse",
|
||||
"Microsoft Entra ID (Azure AD) SSO integration guide",
|
||||
"This changelog describes the changes since `v6.2.0-rc.2`",
|
||||
"Same-named Proxmox clusters from different organizations remain distinct",
|
||||
"overlapping node names and private addresses",
|
||||
"contradicting TLS certificate fingerprints",
|
||||
"connection add handler",
|
||||
"shared identity predicate",
|
||||
"regression test reproduces the reported sequence",
|
||||
"Windows signing decision: Authenticode through SignPath is the mandatory signing backend",
|
||||
"Mobile decision: `no-mobile-impact`",
|
||||
"no companion build upload or public store rollout",
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ func TestPreviousStableForPrereleaseVersionCrossesMinorBoundaries(t *testing.T)
|
|||
want string
|
||||
}{
|
||||
{version: "6.0.5-rc.4", want: "6.0.4"},
|
||||
{version: "6.2.0-rc.2", want: "6.1.2"},
|
||||
{version: "6.2.0-rc.3", want: "6.1.2"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
@ -336,7 +336,8 @@ func TestInstallDockerProofTracksSupportPrereleaseContract(t *testing.T) {
|
|||
assertFileContainsAllNormalized(t, repoFile("docs", "release-control", "v6", "internal", "subsystems", "deployment-installability.md"),
|
||||
"The active support prerelease `v"+version+"` cut sets the repo-root `VERSION`, repo-root `docker-compose.yml` image default, `scripts/install-docker.sh` fallback, and Helm chart release metadata to the same `"+version+"` release version.",
|
||||
"This support prerelease keeps `rollback_version=v"+previous+"`, publishes a versioned public GitHub prerelease plus versioned Docker and Helm artifacts, and does not move stable/latest install pointers or stable semver aliases.",
|
||||
"is a hardening and bugfix cut that supersedes `v6.2.0-rc.1` without dropping anything it carried: it restores unattended-update reliability including in-place repair of already-deployed update units, corrects PBS backup attribution across multiple Proxmox clusters, repairs Proxmox installer registration including per-canonical-type bootstrap grants on combined hosts, hardens the Patrol readiness streaming transport and gates readiness on a completed verdict, ends discovery-policy DNS and SSH retry churn, adds explicit per-metric threshold off toggles, derives SSO callback URLs from the request that reached Pulse, and documents Entra ID SSO integration",
|
||||
"is a focused support correction that supersedes `v6.2.0-rc.2`: adding a Proxmox connection now applies the same endpoint and TLS identity doctrine as later configuration consolidation",
|
||||
"The preceding `v6.2.0-rc.2` candidate used the same support-prerelease path with `rollback_version=v6.1.2` and pinned the same four install surfaces to `6.2.0-rc.2`.",
|
||||
"The preceding `v6.2.0-rc.1` candidate used the same support-prerelease path with `rollback_version=v6.1.2` and pinned the same four install surfaces to `6.2.0-rc.1`.",
|
||||
"The `v"+version+"` server cut is classified `no-mobile-impact`; no companion build upload is part of this cut. The existing mobile candidate programme remains separate, and the release packet must not describe a public store rollout.",
|
||||
"Authenticode signing through SignPath is the canonical Windows signing backend for the `v6.2.0` line.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue