mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
Related to #727: restore default Proxmox ports
This commit is contained in:
@@ -1097,16 +1097,15 @@ func defaultPortForNodeType(nodeType string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeNodeHost ensures hosts always include a scheme and only adds a default port
|
||||
// when the user did not supply a scheme (e.g., bare hostname/IP inputs). If the user
|
||||
// explicitly provides http/https, we respect their choice and avoid forcing a port.
|
||||
// normalizeNodeHost ensures hosts always include a scheme and default port when one
|
||||
// isn't provided. Defaults align with Proxmox APIs (PVE/PMG: 8006, PBS: 8007) while
|
||||
// preserving any explicit scheme/port the user supplies.
|
||||
func normalizeNodeHost(rawHost, nodeType string) (string, error) {
|
||||
host := strings.TrimSpace(rawHost)
|
||||
if host == "" {
|
||||
return "", fmt.Errorf("host is required")
|
||||
}
|
||||
|
||||
userProvidedScheme := strings.HasPrefix(host, "http://") || strings.HasPrefix(host, "https://")
|
||||
scheme := "https"
|
||||
if strings.HasPrefix(host, "http://") {
|
||||
scheme = "http"
|
||||
@@ -1137,7 +1136,7 @@ func normalizeNodeHost(rawHost, nodeType string) (string, error) {
|
||||
parsed.RawQuery = ""
|
||||
parsed.Fragment = ""
|
||||
|
||||
if parsed.Port() == "" && !userProvidedScheme {
|
||||
if parsed.Port() == "" {
|
||||
defaultPort := defaultPortForNodeType(nodeType)
|
||||
if defaultPort != "" {
|
||||
parsed.Host = net.JoinHostPort(parsed.Hostname(), defaultPort)
|
||||
|
||||
@@ -6,19 +6,19 @@ func TestNormalizeNodeHost(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
rawHost string
|
||||
nodeType string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "keeps explicit https without port",
|
||||
rawHost: "https://example.com",
|
||||
nodeType: "pve",
|
||||
want: "https://example.com",
|
||||
},
|
||||
{
|
||||
name: "adds default port for bare pve host",
|
||||
rawHost: "pve.lan",
|
||||
nodeType: "pve",
|
||||
nodeType string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "adds default port to explicit https without port",
|
||||
rawHost: "https://example.com",
|
||||
nodeType: "pve",
|
||||
want: "https://example.com:8006",
|
||||
},
|
||||
{
|
||||
name: "adds default port for bare pve host",
|
||||
rawHost: "pve.lan",
|
||||
nodeType: "pve",
|
||||
want: "https://pve.lan:8006",
|
||||
},
|
||||
{
|
||||
@@ -39,19 +39,19 @@ func TestNormalizeNodeHost(t *testing.T) {
|
||||
nodeType: "pmg",
|
||||
want: "https://[2001:db8::1]:8006",
|
||||
},
|
||||
{
|
||||
name: "drops path segments",
|
||||
rawHost: "https://example.com/api",
|
||||
nodeType: "pve",
|
||||
want: "https://example.com",
|
||||
},
|
||||
{
|
||||
name: "respects explicit http without forcing a port",
|
||||
rawHost: "http://example.com",
|
||||
nodeType: "pve",
|
||||
want: "http://example.com",
|
||||
},
|
||||
}
|
||||
{
|
||||
name: "drops path segments",
|
||||
rawHost: "https://example.com/api",
|
||||
nodeType: "pve",
|
||||
want: "https://example.com:8006",
|
||||
},
|
||||
{
|
||||
name: "adds default port to explicit http scheme",
|
||||
rawHost: "http://example.com",
|
||||
nodeType: "pve",
|
||||
want: "http://example.com:8006",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/rcourtman/pulse-go-rewrite/pkg/pbs"
|
||||
@@ -8,6 +10,42 @@ import (
|
||||
"github.com/rcourtman/pulse-go-rewrite/pkg/proxmox"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultPVEPort = "8006"
|
||||
defaultPBSPort = "8007"
|
||||
)
|
||||
|
||||
// normalizeHostPort ensures we always have a scheme and explicit port when talking to
|
||||
// Proxmox APIs. It preserves existing ports/schemes and strips any path/query segments.
|
||||
func normalizeHostPort(host, defaultPort string) string {
|
||||
trimmed := strings.TrimSpace(host)
|
||||
if trimmed == "" || defaultPort == "" {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
candidate := trimmed
|
||||
if !strings.HasPrefix(candidate, "http://") && !strings.HasPrefix(candidate, "https://") {
|
||||
candidate = "https://" + candidate
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(candidate)
|
||||
if err != nil || parsed.Host == "" {
|
||||
return trimmed
|
||||
}
|
||||
|
||||
// Drop any path fragments so we only persist host:port
|
||||
parsed.Path = ""
|
||||
parsed.RawPath = ""
|
||||
parsed.RawQuery = ""
|
||||
parsed.Fragment = ""
|
||||
|
||||
if parsed.Port() == "" {
|
||||
parsed.Host = net.JoinHostPort(parsed.Hostname(), defaultPort)
|
||||
}
|
||||
|
||||
return parsed.Scheme + "://" + parsed.Host
|
||||
}
|
||||
|
||||
// CreateProxmoxConfig creates a proxmox.ClientConfig from a PVEInstance
|
||||
func CreateProxmoxConfig(node *PVEInstance) proxmox.ClientConfig {
|
||||
user := node.User
|
||||
@@ -16,7 +54,7 @@ func CreateProxmoxConfig(node *PVEInstance) proxmox.ClientConfig {
|
||||
}
|
||||
|
||||
return proxmox.ClientConfig{
|
||||
Host: node.Host,
|
||||
Host: normalizeHostPort(node.Host, defaultPVEPort),
|
||||
User: user,
|
||||
Password: node.Password,
|
||||
TokenName: node.TokenName,
|
||||
@@ -29,7 +67,7 @@ func CreateProxmoxConfig(node *PVEInstance) proxmox.ClientConfig {
|
||||
// CreatePBSConfig creates a pbs.ClientConfig from a PBSInstance
|
||||
func CreatePBSConfig(node *PBSInstance) pbs.ClientConfig {
|
||||
return pbs.ClientConfig{
|
||||
Host: node.Host,
|
||||
Host: normalizeHostPort(node.Host, defaultPBSPort),
|
||||
User: node.User,
|
||||
Password: node.Password,
|
||||
TokenName: node.TokenName,
|
||||
@@ -42,7 +80,7 @@ func CreatePBSConfig(node *PBSInstance) pbs.ClientConfig {
|
||||
// CreatePMGConfig creates a pmg.ClientConfig from a PMGInstance
|
||||
func CreatePMGConfig(node *PMGInstance) pmg.ClientConfig {
|
||||
return pmg.ClientConfig{
|
||||
Host: node.Host,
|
||||
Host: normalizeHostPort(node.Host, defaultPVEPort),
|
||||
User: node.User,
|
||||
Password: node.Password,
|
||||
TokenName: node.TokenName,
|
||||
@@ -59,7 +97,7 @@ func CreateProxmoxConfigFromFields(host, user, password, tokenName, tokenValue,
|
||||
}
|
||||
|
||||
return proxmox.ClientConfig{
|
||||
Host: host,
|
||||
Host: normalizeHostPort(host, defaultPVEPort),
|
||||
User: user,
|
||||
Password: password,
|
||||
TokenName: tokenName,
|
||||
@@ -72,7 +110,7 @@ func CreateProxmoxConfigFromFields(host, user, password, tokenName, tokenValue,
|
||||
// CreatePBSConfigFromFields creates a pbs.ClientConfig from individual fields
|
||||
func CreatePBSConfigFromFields(host, user, password, tokenName, tokenValue, fingerprint string, verifySSL bool) pbs.ClientConfig {
|
||||
return pbs.ClientConfig{
|
||||
Host: host,
|
||||
Host: normalizeHostPort(host, defaultPBSPort),
|
||||
User: user,
|
||||
Password: password,
|
||||
TokenName: tokenName,
|
||||
@@ -85,7 +123,7 @@ func CreatePBSConfigFromFields(host, user, password, tokenName, tokenValue, fing
|
||||
// CreatePMGConfigFromFields creates a pmg.ClientConfig from individual fields
|
||||
func CreatePMGConfigFromFields(host, user, password, tokenName, tokenValue, fingerprint string, verifySSL bool) pmg.ClientConfig {
|
||||
return pmg.ClientConfig{
|
||||
Host: host,
|
||||
Host: normalizeHostPort(host, defaultPVEPort),
|
||||
User: user,
|
||||
Password: password,
|
||||
TokenName: tokenName,
|
||||
|
||||
79
internal/config/client_helpers_test.go
Normal file
79
internal/config/client_helpers_test.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package config
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNormalizeHostPort(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
host string
|
||||
defaultPort string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "adds default port to https host",
|
||||
host: "https://example.com",
|
||||
defaultPort: defaultPVEPort,
|
||||
want: "https://example.com:8006",
|
||||
},
|
||||
{
|
||||
name: "adds default port when scheme missing",
|
||||
host: "pbs.lan",
|
||||
defaultPort: defaultPBSPort,
|
||||
want: "https://pbs.lan:8007",
|
||||
},
|
||||
{
|
||||
name: "preserves existing port and scheme",
|
||||
host: "http://example.com:8443",
|
||||
defaultPort: defaultPVEPort,
|
||||
want: "http://example.com:8443",
|
||||
},
|
||||
{
|
||||
name: "drops path segments before applying port",
|
||||
host: "https://example.com/api",
|
||||
defaultPort: defaultPVEPort,
|
||||
want: "https://example.com:8006",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := normalizeHostPort(tt.host, tt.defaultPort); got != tt.want {
|
||||
t.Fatalf("normalizeHostPort(%q, %q) = %q, want %q", tt.host, tt.defaultPort, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateConfigHelpersNormalizeHosts(t *testing.T) {
|
||||
pveCfg := PVEInstance{
|
||||
Host: "https://pve.local",
|
||||
User: "root@pam",
|
||||
}
|
||||
pveClientCfg := CreateProxmoxConfig(&pveCfg)
|
||||
if pveClientCfg.Host != "https://pve.local:8006" {
|
||||
t.Fatalf("expected default port on PVE host, got %q", pveClientCfg.Host)
|
||||
}
|
||||
|
||||
pbsCfg := PBSInstance{
|
||||
Host: "pbs.local",
|
||||
User: "root@pam",
|
||||
}
|
||||
pbsClientCfg := CreatePBSConfig(&pbsCfg)
|
||||
if pbsClientCfg.Host != "https://pbs.local:8007" {
|
||||
t.Fatalf("expected default PBS port on host, got %q", pbsClientCfg.Host)
|
||||
}
|
||||
|
||||
pmgCfg := PMGInstance{
|
||||
Host: "https://pmg.local/api",
|
||||
User: "root@pam",
|
||||
}
|
||||
pmgClientCfg := CreatePMGConfig(&pmgCfg)
|
||||
if pmgClientCfg.Host != "https://pmg.local:8006" {
|
||||
t.Fatalf("expected default PMG port on host, got %q", pmgClientCfg.Host)
|
||||
}
|
||||
|
||||
fromFields := CreateProxmoxConfigFromFields("https://cluster.local", "root@pam", "", "token!name", "value", "", true)
|
||||
if fromFields.Host != "https://cluster.local:8006" {
|
||||
t.Fatalf("expected default port on host built from fields, got %q", fromFields.Host)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user