Files
elmprodvpn/selective-vpn-api/app/transport_policy_owner_lock.go

60 lines
1.7 KiB
Go

package app
import "strings"
func isTransportClientOwnerLockActive(st TransportClientStatus) bool {
switch st {
case TransportClientUp, TransportClientStarting, TransportClientDegraded:
return true
default:
return false
}
}
func detectTransportOwnerLockConflicts(current, next []TransportPolicyIntent, clients []TransportClient) []TransportConflictRecord {
currentOwners := map[string]string{}
for _, raw := range current {
norm, key, _, err := normalizeTransportIntent(raw)
if err != nil || key == "" || strings.TrimSpace(norm.ClientID) == "" {
continue
}
currentOwners[key] = norm.ClientID
}
if len(currentOwners) == 0 {
return nil
}
activeByClientID := map[string]bool{}
for _, client := range clients {
id := strings.TrimSpace(client.ID)
if id == "" {
continue
}
activeByClientID[id] = isTransportClientOwnerLockActive(client.Status)
}
conflicts := make([]TransportConflictRecord, 0, 4)
for _, raw := range next {
norm, key, _, err := normalizeTransportIntent(raw)
if err != nil || key == "" || strings.TrimSpace(norm.ClientID) == "" {
continue
}
prevOwner, exists := currentOwners[key]
if !exists || prevOwner == norm.ClientID {
continue
}
if !activeByClientID[prevOwner] {
continue
}
conflicts = append(conflicts, TransportConflictRecord{
Key: key,
Type: "owner_lock",
Severity: "block",
Owners: []string{prevOwner, norm.ClientID},
Reason: "selector is locked to active owner; stop previous owner before switching",
SuggestedResolution: "disconnect/stop current owner client, then validate/apply switch again",
})
}
return dedupeTransportConflicts(conflicts)
}