рабочий вариант, но скороть 10 МБит
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
||||
const MaxMeshProductionObservationSinkCapacity = 10000
|
||||
|
||||
type Config struct {
|
||||
BackendURL string
|
||||
ClusterID string
|
||||
ClusterAuthorityPublicKey string
|
||||
ClusterAuthorityFingerprint string
|
||||
@@ -30,7 +29,7 @@ type Config struct {
|
||||
HeartbeatInterval time.Duration
|
||||
EnrollmentPollInterval time.Duration
|
||||
EnrollmentPollTimeout time.Duration
|
||||
MeshSyntheticRuntimeEnabled bool
|
||||
FabricRuntimeEnabled bool
|
||||
MeshProductionForwardingEnabled bool
|
||||
VPNFabricSessionTransportEnabled bool
|
||||
MeshQUICFabricEnabled bool
|
||||
@@ -39,17 +38,18 @@ type Config struct {
|
||||
VPNFabricQUICMaxStreamsPerConn int
|
||||
VPNFabricQUICIdleTTL time.Duration
|
||||
MeshProductionObservationSinkCapacity int
|
||||
MeshListenAddr string
|
||||
MeshListenPortMode string
|
||||
MeshListenAutoPortStart int
|
||||
MeshListenAutoPortEnd int
|
||||
FabricListenAddr string
|
||||
FabricListenPortMode string
|
||||
FabricListenAutoPortStart int
|
||||
FabricListenAutoPortEnd int
|
||||
MeshAdvertiseEndpoint string
|
||||
MeshAdvertiseEndpointsJSON string
|
||||
FabricRegistryRecordsJSON string
|
||||
MeshAdvertiseTransport string
|
||||
MeshConnectivityMode string
|
||||
MeshNATType string
|
||||
MeshLocalSegmentID string
|
||||
MeshSiteID string
|
||||
MeshLocalityGroupID string
|
||||
MeshNATGroupID string
|
||||
MeshSTUNReflexiveEndpoint string
|
||||
MeshSTUNServer string
|
||||
@@ -72,7 +72,6 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
defaultStateDir := filepath.Join(".", ".rap-node-agent")
|
||||
fs := flag.NewFlagSet("rap-node-agent", flag.ContinueOnError)
|
||||
cfg := Config{}
|
||||
fs.StringVar(&cfg.BackendURL, "backend-url", getEnv(env, "RAP_BACKEND_URL", "http://127.0.0.1:8080/api/v1"), "Backend API base URL.")
|
||||
fs.StringVar(&cfg.ClusterID, "cluster-id", getEnv(env, "RAP_CLUSTER_ID", ""), "Cluster ID.")
|
||||
fs.StringVar(&cfg.ClusterAuthorityPublicKey, "cluster-authority-public-key", getEnv(env, "RAP_CLUSTER_AUTHORITY_PUBLIC_KEY", ""), "Pinned cluster authority Ed25519 public key.")
|
||||
fs.StringVar(&cfg.ClusterAuthorityFingerprint, "cluster-authority-fingerprint", getEnv(env, "RAP_CLUSTER_AUTHORITY_FINGERPRINT", ""), "Pinned cluster authority key fingerprint.")
|
||||
@@ -85,26 +84,27 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
fs.StringVar(&cfg.WebIngressSigningKeyID, "web-ingress-signing-key-id", getEnv(env, "RAP_WEB_INGRESS_SIGNING_KEY_ID", ""), "Optional key id for web ingress envelope signatures.")
|
||||
fs.StringVar(&cfg.WebIngressTrustedKeysJSON, "web-ingress-trusted-keys-json", getEnv(env, "RAP_WEB_INGRESS_TRUSTED_KEYS_JSON", ""), "JSON map or array of trusted Ed25519 public keys for web ingress runtime receiver.")
|
||||
fs.StringVar(&cfg.WebIngressRuntimeServiceClasses, "web-ingress-runtime-service-classes", getEnv(env, "RAP_WEB_INGRESS_RUNTIME_SERVICE_CLASSES", ""), "Optional comma-separated allow-list of web ingress runtime service classes accepted by this node.")
|
||||
fs.BoolVar(&cfg.MeshSyntheticRuntimeEnabled, "mesh-synthetic-runtime-enabled", getEnvBool(env, "RAP_MESH_SYNTHETIC_RUNTIME_ENABLED", false), "Enable C17A synthetic fabric probe runtime. Disabled by default.")
|
||||
fs.BoolVar(&cfg.FabricRuntimeEnabled, "fabric-runtime-enabled", getEnvBool(env, "RAP_FABRIC_RUNTIME_ENABLED", false), "Enable C17A synthetic fabric probe runtime. Disabled by default.")
|
||||
fs.BoolVar(&cfg.MeshProductionForwardingEnabled, "mesh-production-forwarding-enabled", getEnvBool(env, "RAP_MESH_PRODUCTION_FORWARDING_ENABLED", false), "Enable production fabric-control direct next-hop forwarding gate. Disabled by default.")
|
||||
fs.BoolVar(&cfg.VPNFabricSessionTransportEnabled, "vpn-fabric-session-transport-enabled", getEnvBool(env, "RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED", false), "Route VPN packet transport over persistent fabric session when explicitly enabled. Disabled by default.")
|
||||
fs.BoolVar(&cfg.MeshQUICFabricEnabled, "mesh-quic-fabric-enabled", getEnvBool(env, "RAP_MESH_QUIC_FABRIC_ENABLED", false), "Enable QUIC/UDP fabric listener. Disabled by default.")
|
||||
fs.StringVar(&cfg.MeshQUICFabricListenAddr, "mesh-quic-fabric-listen-addr", getEnv(env, "RAP_MESH_QUIC_FABRIC_LISTEN_ADDR", ""), "Listen address for QUIC/UDP fabric endpoint, for example :19443.")
|
||||
fs.IntVar(&cfg.VPNFabricSessionStreamShards, "vpn-fabric-session-stream-shards", getEnvInt(env, "RAP_VPN_FABRIC_SESSION_STREAM_SHARDS", 4), "VPN fabric-session stream shards per traffic class.")
|
||||
fs.IntVar(&cfg.VPNFabricSessionStreamShards, "vpn-fabric-session-stream-shards", getEnvInt(env, "RAP_VPN_FABRIC_SESSION_STREAM_SHARDS", 8), "VPN fabric-session stream shards per traffic class.")
|
||||
fs.IntVar(&cfg.VPNFabricQUICMaxStreamsPerConn, "vpn-fabric-quic-max-streams-per-conn", getEnvInt(env, "RAP_VPN_FABRIC_QUIC_MAX_STREAMS_PER_CONN", 64), "Maximum logical fabric-session streams per cached VPN QUIC carrier connection.")
|
||||
fs.DurationVar(&cfg.VPNFabricQUICIdleTTL, "vpn-fabric-quic-idle-ttl", time.Duration(getEnvInt(env, "RAP_VPN_FABRIC_QUIC_IDLE_TTL_SECONDS", 300))*time.Second, "Idle TTL for cached VPN QUIC carrier connections.")
|
||||
fs.IntVar(&cfg.MeshProductionObservationSinkCapacity, "mesh-production-observation-sink-capacity", getEnvSignedInt(env, "RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY", 0), "Bounded local metadata-only production envelope observation sink capacity. Disabled when 0.")
|
||||
fs.StringVar(&cfg.MeshListenAddr, "mesh-listen-addr", getEnv(env, "RAP_MESH_LISTEN_ADDR", ""), "Listen address for disabled-by-default historical synthetic mesh HTTP endpoint.")
|
||||
fs.StringVar(&cfg.MeshListenPortMode, "mesh-listen-port-mode", getEnv(env, "RAP_MESH_LISTEN_PORT_MODE", "manual"), "Mesh listen port behavior: manual, auto, or disabled.")
|
||||
fs.IntVar(&cfg.MeshListenAutoPortStart, "mesh-listen-auto-port-start", getEnvInt(env, "RAP_MESH_LISTEN_AUTO_PORT_START", 19131), "First port used when mesh listen port mode is auto.")
|
||||
fs.IntVar(&cfg.MeshListenAutoPortEnd, "mesh-listen-auto-port-end", getEnvInt(env, "RAP_MESH_LISTEN_AUTO_PORT_END", 19231), "Last port used when mesh listen port mode is auto.")
|
||||
fs.StringVar(&cfg.FabricListenAddr, "fabric-listen-addr", getEnv(env, "RAP_FABRIC_LISTEN_ADDR", ""), "Optional node listener address used by the QUIC fabric runtime contract.")
|
||||
fs.StringVar(&cfg.FabricListenPortMode, "fabric-listen-port-mode", getEnv(env, "RAP_FABRIC_LISTEN_PORT_MODE", "manual"), "Fabric listen port behavior: manual, auto, or disabled.")
|
||||
fs.IntVar(&cfg.FabricListenAutoPortStart, "fabric-listen-auto-port-start", getEnvInt(env, "RAP_FABRIC_LISTEN_AUTO_PORT_START", 19131), "First port used when fabric listen port mode is auto.")
|
||||
fs.IntVar(&cfg.FabricListenAutoPortEnd, "fabric-listen-auto-port-end", getEnvInt(env, "RAP_FABRIC_LISTEN_AUTO_PORT_END", 19231), "Last port used when fabric listen port mode is auto.")
|
||||
fs.StringVar(&cfg.MeshAdvertiseEndpoint, "mesh-advertise-endpoint", getEnv(env, "RAP_MESH_ADVERTISE_ENDPOINT", ""), "Advertised mesh endpoint reported to the Control Plane. Empty disables endpoint reporting.")
|
||||
fs.StringVar(&cfg.MeshAdvertiseEndpointsJSON, "mesh-advertise-endpoints-json", getEnv(env, "RAP_MESH_ADVERTISE_ENDPOINTS_JSON", ""), "JSON array of advertised mesh endpoint candidates, including private/corporate endpoints.")
|
||||
fs.StringVar(&cfg.FabricRegistryRecordsJSON, "fabric-registry-records-json", getEnv(env, "RAP_FABRIC_REGISTRY_RECORDS_JSON", ""), "JSON array of signed QUIC-only fabric registry gossip records used as bootstrap discovery seeds.")
|
||||
fs.StringVar(&cfg.MeshAdvertiseTransport, "mesh-advertise-transport", getEnv(env, "RAP_MESH_ADVERTISE_TRANSPORT", "quic"), "Transport label for the advertised mesh endpoint.")
|
||||
fs.StringVar(&cfg.MeshConnectivityMode, "mesh-connectivity-mode", getEnv(env, "RAP_MESH_CONNECTIVITY_MODE", "direct"), "Connectivity mode reported with the advertised mesh endpoint.")
|
||||
fs.StringVar(&cfg.MeshNATType, "mesh-nat-type", getEnv(env, "RAP_MESH_NAT_TYPE", "unknown"), "NAT type hint reported with the advertised mesh endpoint.")
|
||||
fs.StringVar(&cfg.MeshLocalSegmentID, "mesh-local-segment-id", getEnv(env, "RAP_MESH_LOCAL_SEGMENT_ID", ""), "Optional local LAN/site segment ID advertised with QUIC endpoint candidates.")
|
||||
fs.StringVar(&cfg.MeshSiteID, "mesh-site-id", getEnv(env, "RAP_MESH_SITE_ID", ""), "Optional physical or logical site identifier advertised with QUIC endpoint candidates.")
|
||||
fs.StringVar(&cfg.MeshLocalityGroupID, "mesh-locality-group-id", getEnv(env, "RAP_MESH_LOCALITY_GROUP_ID", ""), "Optional locality group identifier used to decide whether private QUIC endpoints are actually local.")
|
||||
fs.StringVar(&cfg.MeshNATGroupID, "mesh-nat-group-id", getEnv(env, "RAP_MESH_NAT_GROUP_ID", ""), "Optional NAT group ID advertised with QUIC endpoint candidates.")
|
||||
fs.StringVar(&cfg.MeshSTUNReflexiveEndpoint, "mesh-stun-reflexive-endpoint", getEnv(env, "RAP_MESH_STUN_REFLEXIVE_ENDPOINT", ""), "Optional STUN-discovered reflexive QUIC endpoint, for example quic://203.0.113.10:19443.")
|
||||
fs.StringVar(&cfg.MeshSTUNServer, "mesh-stun-server", getEnv(env, "RAP_MESH_STUN_SERVER", ""), "Optional STUN server name used to discover the reflexive endpoint.")
|
||||
@@ -127,21 +127,20 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.BackendURL = strings.TrimRight(strings.TrimSpace(cfg.BackendURL), "/")
|
||||
cfg.ClusterID = strings.TrimSpace(cfg.ClusterID)
|
||||
cfg.ClusterAuthorityPublicKey = strings.TrimSpace(cfg.ClusterAuthorityPublicKey)
|
||||
cfg.ClusterAuthorityFingerprint = strings.TrimSpace(cfg.ClusterAuthorityFingerprint)
|
||||
cfg.JoinToken = strings.TrimSpace(cfg.JoinToken)
|
||||
cfg.NodeName = strings.TrimSpace(cfg.NodeName)
|
||||
cfg.StateDir = strings.TrimSpace(cfg.StateDir)
|
||||
cfg.MeshListenAddr = strings.TrimSpace(cfg.MeshListenAddr)
|
||||
cfg.FabricListenAddr = strings.TrimSpace(cfg.FabricListenAddr)
|
||||
cfg.MeshQUICFabricListenAddr = strings.TrimSpace(cfg.MeshQUICFabricListenAddr)
|
||||
cfg.MeshListenPortMode = strings.ToLower(strings.TrimSpace(cfg.MeshListenPortMode))
|
||||
cfg.FabricListenPortMode = strings.ToLower(strings.TrimSpace(cfg.FabricListenPortMode))
|
||||
if cfg.VPNFabricSessionStreamShards <= 0 {
|
||||
cfg.VPNFabricSessionStreamShards = 4
|
||||
cfg.VPNFabricSessionStreamShards = 8
|
||||
}
|
||||
if cfg.VPNFabricSessionStreamShards > 64 {
|
||||
cfg.VPNFabricSessionStreamShards = 64
|
||||
if cfg.VPNFabricSessionStreamShards > 128 {
|
||||
cfg.VPNFabricSessionStreamShards = 128
|
||||
}
|
||||
if cfg.VPNFabricQUICMaxStreamsPerConn <= 0 {
|
||||
cfg.VPNFabricQUICMaxStreamsPerConn = 64
|
||||
@@ -156,16 +155,15 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
if cfg.MeshAdvertiseTransport == "" {
|
||||
cfg.MeshAdvertiseTransport = "quic"
|
||||
}
|
||||
cfg.MeshAdvertiseTransport = normalizeLegacyAdvertiseTransport(cfg.MeshAdvertiseTransport)
|
||||
cfg.MeshAdvertiseEndpoint = normalizeLegacyEndpointSchemeToQUIC(cfg.MeshAdvertiseEndpoint)
|
||||
cfg.MeshConnectivityMode = strings.TrimSpace(cfg.MeshConnectivityMode)
|
||||
cfg.MeshNATType = strings.TrimSpace(cfg.MeshNATType)
|
||||
cfg.MeshLocalSegmentID = strings.TrimSpace(cfg.MeshLocalSegmentID)
|
||||
cfg.MeshSiteID = strings.TrimSpace(cfg.MeshSiteID)
|
||||
cfg.MeshLocalityGroupID = strings.TrimSpace(cfg.MeshLocalityGroupID)
|
||||
cfg.MeshNATGroupID = strings.TrimSpace(cfg.MeshNATGroupID)
|
||||
cfg.MeshSTUNReflexiveEndpoint = normalizeLegacyEndpointSchemeToQUIC(strings.TrimRight(strings.TrimSpace(cfg.MeshSTUNReflexiveEndpoint), "/"))
|
||||
cfg.MeshSTUNReflexiveEndpoint = strings.TrimRight(strings.TrimSpace(cfg.MeshSTUNReflexiveEndpoint), "/")
|
||||
cfg.MeshSTUNServer = strings.TrimSpace(cfg.MeshSTUNServer)
|
||||
cfg.MeshRelayNodeID = strings.TrimSpace(cfg.MeshRelayNodeID)
|
||||
cfg.MeshRelayEndpoint = normalizeLegacyEndpointSchemeToQUIC(strings.TrimRight(strings.TrimSpace(cfg.MeshRelayEndpoint), "/"))
|
||||
cfg.MeshRelayEndpoint = strings.TrimRight(strings.TrimSpace(cfg.MeshRelayEndpoint), "/")
|
||||
cfg.MeshRegion = strings.TrimSpace(cfg.MeshRegion)
|
||||
cfg.MeshSyntheticConfigPath = strings.TrimSpace(cfg.MeshSyntheticConfigPath)
|
||||
cfg.MeshPeerEndpointsJSON = strings.TrimSpace(cfg.MeshPeerEndpointsJSON)
|
||||
@@ -177,8 +175,8 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
cfg.RemoteWorkspaceRealAdapterCommand = strings.TrimSpace(cfg.RemoteWorkspaceRealAdapterCommand)
|
||||
cfg.RemoteWorkspaceRealAdapterArgsJSON = strings.TrimSpace(cfg.RemoteWorkspaceRealAdapterArgsJSON)
|
||||
cfg.RemoteWorkspaceRealAdapterWorkDir = strings.TrimSpace(cfg.RemoteWorkspaceRealAdapterWorkDir)
|
||||
if cfg.BackendURL == "" {
|
||||
return Config{}, errors.New("backend URL is required")
|
||||
if cfg.FabricRegistryRecordsJSON == "" {
|
||||
return Config{}, errors.New("fabric registry records are required")
|
||||
}
|
||||
if cfg.NodeName == "" {
|
||||
return Config{}, errors.New("node name is required")
|
||||
@@ -204,30 +202,30 @@ func Load(args []string, env map[string]string) (Config, error) {
|
||||
if cfg.FabricRegistryRecordsJSON != "" && !isJSONArray(cfg.FabricRegistryRecordsJSON) {
|
||||
return Config{}, errors.New("fabric registry records must be a JSON array")
|
||||
}
|
||||
switch cfg.MeshListenPortMode {
|
||||
switch cfg.FabricListenPortMode {
|
||||
case "", "manual", "auto", "disabled":
|
||||
if cfg.MeshListenPortMode == "" {
|
||||
cfg.MeshListenPortMode = "manual"
|
||||
if cfg.FabricListenPortMode == "" {
|
||||
cfg.FabricListenPortMode = "manual"
|
||||
}
|
||||
default:
|
||||
return Config{}, errors.New("mesh listen port mode must be manual, auto, or disabled")
|
||||
return Config{}, errors.New("fabric listen port mode must be manual, auto, or disabled")
|
||||
}
|
||||
if cfg.MeshListenAutoPortStart <= 0 || cfg.MeshListenAutoPortEnd <= 0 {
|
||||
return Config{}, errors.New("mesh listen auto port range must be positive")
|
||||
if cfg.FabricListenAutoPortStart <= 0 || cfg.FabricListenAutoPortEnd <= 0 {
|
||||
return Config{}, errors.New("fabric listen auto port range must be positive")
|
||||
}
|
||||
if cfg.MeshListenAutoPortStart > cfg.MeshListenAutoPortEnd {
|
||||
return Config{}, errors.New("mesh listen auto port start must be less than or equal to end")
|
||||
if cfg.FabricListenAutoPortStart > cfg.FabricListenAutoPortEnd {
|
||||
return Config{}, errors.New("fabric listen auto port start must be less than or equal to end")
|
||||
}
|
||||
if !isQUICAdvertiseTransport(cfg.MeshAdvertiseTransport) {
|
||||
return Config{}, errors.New("mesh advertise transport must be a QUIC transport label")
|
||||
}
|
||||
if hasLegacyEndpointScheme(cfg.MeshAdvertiseEndpoint) {
|
||||
if hasUnsupportedEndpointScheme(cfg.MeshAdvertiseEndpoint) {
|
||||
return Config{}, errors.New("mesh advertise endpoint must be a QUIC endpoint")
|
||||
}
|
||||
if cfg.MeshSTUNReflexiveEndpoint != "" && hasLegacyEndpointScheme(cfg.MeshSTUNReflexiveEndpoint) {
|
||||
if cfg.MeshSTUNReflexiveEndpoint != "" && hasUnsupportedEndpointScheme(cfg.MeshSTUNReflexiveEndpoint) {
|
||||
return Config{}, errors.New("mesh STUN reflexive endpoint must be a QUIC endpoint")
|
||||
}
|
||||
if cfg.MeshRelayEndpoint != "" && hasLegacyEndpointScheme(cfg.MeshRelayEndpoint) {
|
||||
if cfg.MeshRelayEndpoint != "" && hasUnsupportedEndpointScheme(cfg.MeshRelayEndpoint) {
|
||||
return Config{}, errors.New("mesh relay endpoint must be a QUIC endpoint")
|
||||
}
|
||||
return cfg, nil
|
||||
@@ -242,36 +240,12 @@ func isQUICAdvertiseTransport(label string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeLegacyAdvertiseTransport(label string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(label)) {
|
||||
case "direct_http", "direct_https", "direct_tcp_tls", "http", "https", "ws", "wss", "websocket":
|
||||
return "direct_quic"
|
||||
case "outbound_reverse", "reverse", "reverse_outbound":
|
||||
return "reverse_quic"
|
||||
case "relay", "relay_control":
|
||||
return "relay_quic"
|
||||
default:
|
||||
return strings.TrimSpace(label)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeLegacyEndpointSchemeToQUIC(endpoint string) string {
|
||||
endpoint = strings.TrimRight(strings.TrimSpace(endpoint), "/")
|
||||
lower := strings.ToLower(endpoint)
|
||||
for _, prefix := range []string{"http://", "https://", "ws://", "wss://"} {
|
||||
if strings.HasPrefix(lower, prefix) {
|
||||
return "quic://" + endpoint[len(prefix):]
|
||||
}
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func hasLegacyEndpointScheme(endpoint string) bool {
|
||||
func hasUnsupportedEndpointScheme(endpoint string) bool {
|
||||
endpoint = strings.ToLower(strings.TrimSpace(endpoint))
|
||||
return strings.HasPrefix(endpoint, "http://") ||
|
||||
strings.HasPrefix(endpoint, "https://") ||
|
||||
strings.HasPrefix(endpoint, "ws://") ||
|
||||
strings.HasPrefix(endpoint, "wss://")
|
||||
if endpoint == "" || !strings.Contains(endpoint, "://") {
|
||||
return false
|
||||
}
|
||||
return !strings.HasPrefix(endpoint, "quic://")
|
||||
}
|
||||
|
||||
func isJSONArray(value string) bool {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
cfg, err := Load([]string{"-node-name", "node-b"}, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1/",
|
||||
"RAP_CLUSTER_ID": "cluster-1",
|
||||
"RAP_CLUSTER_AUTHORITY_PUBLIC_KEY": "public-key-b64",
|
||||
"RAP_CLUSTER_AUTHORITY_FINGERPRINT": "rap-ca-ed25519-test",
|
||||
@@ -23,7 +23,7 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
"RAP_HEARTBEAT_INTERVAL_SECONDS": "7",
|
||||
"RAP_ENROLLMENT_POLL_INTERVAL_SECONDS": "3",
|
||||
"RAP_ENROLLMENT_POLL_TIMEOUT_SECONDS": "30",
|
||||
"RAP_MESH_SYNTHETIC_RUNTIME_ENABLED": "true",
|
||||
"RAP_FABRIC_RUNTIME_ENABLED": "true",
|
||||
"RAP_MESH_PRODUCTION_FORWARDING_ENABLED": "true",
|
||||
"RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED": "true",
|
||||
"RAP_MESH_QUIC_FABRIC_ENABLED": "true",
|
||||
@@ -32,17 +32,18 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
"RAP_VPN_FABRIC_QUIC_MAX_STREAMS_PER_CONN": "24",
|
||||
"RAP_VPN_FABRIC_QUIC_IDLE_TTL_SECONDS": "120",
|
||||
"RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY": "5",
|
||||
"RAP_MESH_LISTEN_ADDR": "127.0.0.1:19001",
|
||||
"RAP_MESH_LISTEN_PORT_MODE": "auto",
|
||||
"RAP_MESH_LISTEN_AUTO_PORT_START": "19010",
|
||||
"RAP_MESH_LISTEN_AUTO_PORT_END": "19020",
|
||||
"RAP_FABRIC_LISTEN_ADDR": "127.0.0.1:19001",
|
||||
"RAP_FABRIC_LISTEN_PORT_MODE": "auto",
|
||||
"RAP_FABRIC_LISTEN_AUTO_PORT_START": "19010",
|
||||
"RAP_FABRIC_LISTEN_AUTO_PORT_END": "19020",
|
||||
"RAP_MESH_ADVERTISE_ENDPOINT": "quic://node-a.example.test:19443/",
|
||||
"RAP_MESH_ADVERTISE_ENDPOINTS_JSON": `[{"endpoint_id":"node-a-lan","address":"10.10.0.20:19001"}]`,
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": ` [{"schema":"rap.fabric.registry.gossip_record.v1","service_class":"control-api"}] `,
|
||||
"RAP_MESH_ADVERTISE_TRANSPORT": "direct_quic",
|
||||
"RAP_MESH_CONNECTIVITY_MODE": "outbound_only",
|
||||
"RAP_MESH_NAT_TYPE": "symmetric",
|
||||
"RAP_MESH_LOCAL_SEGMENT_ID": "site-a",
|
||||
"RAP_MESH_SITE_ID": "home",
|
||||
"RAP_MESH_LOCALITY_GROUP_ID": "home-lan",
|
||||
"RAP_MESH_NAT_GROUP_ID": "nat-a",
|
||||
"RAP_MESH_STUN_REFLEXIVE_ENDPOINT": "quic://203.0.113.20:19443/",
|
||||
"RAP_MESH_STUN_SERVER": "stun.example.test:3478",
|
||||
@@ -50,7 +51,7 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
"RAP_MESH_RELAY_ENDPOINT": "quic://node-r.example.test:19443/",
|
||||
"RAP_MESH_REGION": "eu",
|
||||
"RAP_MESH_SYNTHETIC_CONFIG": "/tmp/rap-node/mesh-synthetic.json",
|
||||
"RAP_MESH_PEER_ENDPOINTS_JSON": `{"node-b":"http://127.0.0.1:19002"}`,
|
||||
"RAP_MESH_PEER_ENDPOINTS_JSON": `{"node-b":"quic://127.0.0.1:19002"}`,
|
||||
"RAP_MESH_SYNTHETIC_ROUTES_JSON": `[{"route_id":"route-1"}]`,
|
||||
"RAP_REMOTE_WORKSPACE_REAL_ADAPTER_ENABLED": "true",
|
||||
"RAP_REMOTE_WORKSPACE_REAL_ADAPTER_COMMAND": " /opt/rap/bin/rdp-worker ",
|
||||
@@ -60,9 +61,6 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("load config: %v", err)
|
||||
}
|
||||
if cfg.BackendURL != "http://backend/api/v1" {
|
||||
t.Fatalf("BackendURL = %q", cfg.BackendURL)
|
||||
}
|
||||
if cfg.NodeName != "node-b" {
|
||||
t.Fatalf("NodeName = %q", cfg.NodeName)
|
||||
}
|
||||
@@ -87,8 +85,8 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
cfg.WebIngressRuntimeServiceClasses != "platform_admin, cluster_admin" {
|
||||
t.Fatalf("unexpected web ingress key config: %+v", cfg)
|
||||
}
|
||||
if !cfg.MeshSyntheticRuntimeEnabled {
|
||||
t.Fatal("MeshSyntheticRuntimeEnabled = false, want true")
|
||||
if !cfg.FabricRuntimeEnabled {
|
||||
t.Fatal("FabricRuntimeEnabled = false, want true")
|
||||
}
|
||||
if !cfg.MeshProductionForwardingEnabled {
|
||||
t.Fatal("MeshProductionForwardingEnabled = false, want true")
|
||||
@@ -111,11 +109,11 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
if cfg.MeshProductionObservationSinkCapacity != 5 {
|
||||
t.Fatalf("MeshProductionObservationSinkCapacity = %d, want 5", cfg.MeshProductionObservationSinkCapacity)
|
||||
}
|
||||
if cfg.MeshListenAddr != "127.0.0.1:19001" {
|
||||
t.Fatalf("MeshListenAddr = %q", cfg.MeshListenAddr)
|
||||
if cfg.FabricListenAddr != "127.0.0.1:19001" {
|
||||
t.Fatalf("FabricListenAddr = %q", cfg.FabricListenAddr)
|
||||
}
|
||||
if cfg.MeshListenPortMode != "auto" || cfg.MeshListenAutoPortStart != 19010 || cfg.MeshListenAutoPortEnd != 19020 {
|
||||
t.Fatalf("unexpected mesh listen port config: %+v", cfg)
|
||||
if cfg.FabricListenPortMode != "auto" || cfg.FabricListenAutoPortStart != 19010 || cfg.FabricListenAutoPortEnd != 19020 {
|
||||
t.Fatalf("unexpected fabric listen port config: %+v", cfg)
|
||||
}
|
||||
if cfg.MeshAdvertiseEndpoint != "quic://node-a.example.test:19443" ||
|
||||
cfg.MeshAdvertiseEndpointsJSON == "" ||
|
||||
@@ -123,7 +121,8 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
cfg.MeshAdvertiseTransport != "direct_quic" ||
|
||||
cfg.MeshConnectivityMode != "outbound_only" ||
|
||||
cfg.MeshNATType != "symmetric" ||
|
||||
cfg.MeshLocalSegmentID != "site-a" ||
|
||||
cfg.MeshSiteID != "home" ||
|
||||
cfg.MeshLocalityGroupID != "home-lan" ||
|
||||
cfg.MeshNATGroupID != "nat-a" ||
|
||||
cfg.MeshSTUNReflexiveEndpoint != "quic://203.0.113.20:19443" ||
|
||||
cfg.MeshSTUNServer != "stun.example.test:3478" ||
|
||||
@@ -146,10 +145,24 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigLoadsLocalityGroup(t *testing.T) {
|
||||
cfg, err := Load(nil, map[string]string{
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
"RAP_MESH_LOCALITY_GROUP_ID": "home-lan",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("load config: %v", err)
|
||||
}
|
||||
if cfg.MeshLocalityGroupID != "home-lan" {
|
||||
t.Fatalf("unexpected locality group: %+v", cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigDefaultsEnrollmentPollingToNoTimeout(t *testing.T) {
|
||||
cfg, err := Load(nil, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("load config: %v", err)
|
||||
@@ -168,10 +181,31 @@ func TestLoadConfigDefaultsEnrollmentPollingToNoTimeout(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigRequiresFabricBootstrap(t *testing.T) {
|
||||
_, err := Load([]string{
|
||||
"--node-name", "node-a",
|
||||
"--state-dir", t.TempDir(),
|
||||
"--fabric-registry-records-json", `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
}, map[string]string{})
|
||||
if err != nil {
|
||||
t.Fatalf("load config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigRejectsMissingFabricBootstrap(t *testing.T) {
|
||||
_, err := Load([]string{
|
||||
"--node-name", "node-a",
|
||||
"--state-dir", t.TempDir(),
|
||||
}, map[string]string{})
|
||||
if err == nil || !strings.Contains(err.Error(), "fabric registry records are required") {
|
||||
t.Fatalf("expected fabric validation error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigRejectsNegativeProductionObservationSinkCapacity(t *testing.T) {
|
||||
_, err := Load(nil, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
"RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY": "-1",
|
||||
})
|
||||
if err == nil {
|
||||
@@ -181,8 +215,8 @@ func TestLoadConfigRejectsNegativeProductionObservationSinkCapacity(t *testing.T
|
||||
|
||||
func TestLoadConfigRejectsTooLargeProductionObservationSinkCapacity(t *testing.T) {
|
||||
_, err := Load(nil, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
"RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY": "10001",
|
||||
})
|
||||
if err == nil {
|
||||
@@ -190,32 +224,26 @@ func TestLoadConfigRejectsTooLargeProductionObservationSinkCapacity(t *testing.T
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigNormalizesLegacyMeshAdvertiseTransport(t *testing.T) {
|
||||
cfg, err := Load(nil, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_MESH_ADVERTISE_ENDPOINT": "quic://node-a.example.test:19443",
|
||||
"RAP_MESH_ADVERTISE_TRANSPORT": "wss",
|
||||
func TestLoadConfigRejectsDisallowedMeshAdvertiseTransport(t *testing.T) {
|
||||
_, err := Load(nil, map[string]string{
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
"RAP_MESH_ADVERTISE_ENDPOINT": "quic://node-a.example.test:19443",
|
||||
"RAP_MESH_ADVERTISE_TRANSPORT": "wss",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Load returned error for legacy mesh advertise transport migration: %v", err)
|
||||
}
|
||||
if cfg.MeshAdvertiseTransport != "direct_quic" {
|
||||
t.Fatalf("transport = %q, want direct_quic", cfg.MeshAdvertiseTransport)
|
||||
if err == nil || !strings.Contains(err.Error(), "QUIC transport label") {
|
||||
t.Fatalf("expected QUIC transport rejection, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadConfigNormalizesLegacyMeshAdvertiseEndpointScheme(t *testing.T) {
|
||||
cfg, err := Load(nil, map[string]string{
|
||||
"RAP_BACKEND_URL": "http://backend/api/v1",
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_MESH_ADVERTISE_ENDPOINT": "https://node-a.example.test:443",
|
||||
"RAP_MESH_ADVERTISE_TRANSPORT": "direct_quic",
|
||||
func TestLoadConfigRejectsDisallowedMeshAdvertiseEndpointScheme(t *testing.T) {
|
||||
_, err := Load(nil, map[string]string{
|
||||
"RAP_NODE_NAME": "node-a",
|
||||
"RAP_FABRIC_REGISTRY_RECORDS_JSON": `[{"schema":"rap.fabric.registry.gossip_record.v1"}]`,
|
||||
"RAP_MESH_ADVERTISE_ENDPOINT": "https://node-a.example.test:443",
|
||||
"RAP_MESH_ADVERTISE_TRANSPORT": "direct_quic",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Load returned error for legacy mesh advertise endpoint migration: %v", err)
|
||||
}
|
||||
if cfg.MeshAdvertiseEndpoint != "quic://node-a.example.test:443" {
|
||||
t.Fatalf("endpoint = %q, want quic scheme", cfg.MeshAdvertiseEndpoint)
|
||||
if err == nil || !strings.Contains(err.Error(), "QUIC endpoint") {
|
||||
t.Fatalf("expected QUIC endpoint rejection, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user