рабочий вариант, но скороть 10 МБит
build / backend (push) Has been cancelled
build / node-agent (push) Has been cancelled
build / worker (push) Has been cancelled

This commit is contained in:
2026-05-22 21:46:49 +03:00
parent 469fa0e860
commit 20d361a886
280 changed files with 954890 additions and 18524 deletions
@@ -311,6 +311,69 @@ func (s *PostgresStore) ListClusterNodes(ctx context.Context, clusterID string)
return out, rows.Err()
}
func (s *PostgresStore) RegisterFabricNode(ctx context.Context, input RegisterFabricNodeInput) (ClusterNode, error) {
tx, err := s.db.Begin(ctx)
if err != nil {
return ClusterNode{}, err
}
defer tx.Rollback(ctx)
now := time.Now().UTC()
nodeID := uuid.NewString()
row := tx.QueryRow(ctx, `
INSERT INTO nodes (
id, owner_organization_id, node_key, name, ownership_type, registration_status, health_status,
version_state, partition_state, reported_version, metadata, created_at, updated_at
) VALUES ($1::uuid, $2::uuid, $3, $4, $5, 'active', 'healthy', 'current', 'healthy', $6, $7::jsonb, $8, $8)
ON CONFLICT (node_key) DO UPDATE SET
owner_organization_id = COALESCE(EXCLUDED.owner_organization_id, nodes.owner_organization_id),
name = EXCLUDED.name,
ownership_type = EXCLUDED.ownership_type,
registration_status = 'active',
health_status = 'healthy',
reported_version = COALESCE(EXCLUDED.reported_version, nodes.reported_version),
metadata = nodes.metadata || EXCLUDED.metadata,
updated_at = EXCLUDED.updated_at
RETURNING id::text
`, nodeID, input.OwnerOrganizationID, input.NodeKey, input.Name, input.OwnershipType, input.ReportedVersion, []byte(input.Metadata), now)
if err := row.Scan(&nodeID); err != nil {
return ClusterNode{}, err
}
if _, err := tx.Exec(ctx, `
INSERT INTO cluster_memberships (cluster_id, node_id, membership_status, joined_at, last_seen_at, metadata)
VALUES ($1::uuid, $2::uuid, 'active', $3, $3, $4::jsonb)
ON CONFLICT (cluster_id, node_id) DO UPDATE SET
membership_status = 'active',
last_seen_at = EXCLUDED.last_seen_at,
metadata = cluster_memberships.metadata || EXCLUDED.metadata
`, input.ClusterID, nodeID, now, []byte(`{"source":"fabric_control_register"}`)); err != nil {
return ClusterNode{}, err
}
itemRow := tx.QueryRow(ctx, `
SELECT n.id::text, n.owner_organization_id::text, n.node_key, n.name, n.ownership_type,
n.registration_status, n.health_status, n.version_state, n.partition_state,
n.reported_version, n.last_seen_at, cm.membership_status, cm.metadata,
ng.id::text, ng.name,
n.created_at, n.updated_at
FROM cluster_memberships cm
JOIN nodes n ON n.id = cm.node_id
LEFT JOIN cluster_node_group_memberships ngm ON ngm.cluster_id = cm.cluster_id AND ngm.node_id = cm.node_id
LEFT JOIN cluster_node_groups ng ON ng.cluster_id = ngm.cluster_id AND ng.id = ngm.group_id
WHERE cm.cluster_id = $1::uuid
AND cm.node_id = $2::uuid
`, input.ClusterID, nodeID)
item, err := scanClusterNode(itemRow)
if err != nil {
return ClusterNode{}, err
}
if err := tx.Commit(ctx); err != nil {
return ClusterNode{}, err
}
return item, nil
}
func (s *PostgresStore) ListNodeGroups(ctx context.Context, clusterID string) ([]ClusterNodeGroup, error) {
rows, err := s.db.Query(ctx, `
SELECT id::text, cluster_id::text, parent_group_id::text, name, description,
@@ -511,7 +574,7 @@ func (s *PostgresStore) CreateJoinRequest(ctx context.Context, input CreateJoinR
return item, nil
}
func (s *PostgresStore) GetJoinRequestForBootstrap(ctx context.Context, input GetJoinRequestBootstrapInput) (NodeJoinRequest, error) {
func (s *PostgresStore) GetJoinRequestForJoin(ctx context.Context, input GetJoinRequestJoinInput) (NodeJoinRequest, error) {
row := s.db.QueryRow(ctx, `
SELECT id::text, cluster_id::text, join_token_id::text, node_name, node_fingerprint, public_key,
reported_capabilities, reported_facts, requested_roles, status, reviewed_by_user_id::text,
@@ -666,7 +729,7 @@ func (s *PostgresStore) ApproveJoinRequest(ctx context.Context, input ApproveJoi
}
return ApprovedJoinRequest{
JoinRequest: updated,
Bootstrap: NodeBootstrap{
JoinContract: NodeJoinContract{
NodeID: nodeID,
ClusterID: input.ClusterID,
IdentityStatus: "active",
@@ -1310,6 +1373,17 @@ func (s *PostgresStore) listReleaseArtifacts(ctx context.Context, releaseID stri
return out, rows.Err()
}
func (s *PostgresStore) GetReleaseArtifact(ctx context.Context, clusterID, artifactID string) (ReleaseArtifact, error) {
row := s.db.QueryRow(ctx, `
SELECT id::text, release_id::text, cluster_id::text, product, version, os, arch,
install_type, kind, url, sha256, size_bytes, signature, metadata, created_at
FROM release_artifacts
WHERE cluster_id = $1::uuid
AND id = $2::uuid
`, clusterID, artifactID)
return scanReleaseArtifact(row)
}
func (s *PostgresStore) ListNodeUpdateServiceCandidates(ctx context.Context, clusterID string) ([]NodeUpdateServiceCandidate, error) {
rows, err := s.db.Query(ctx, `
SELECT n.id::text,
@@ -4922,9 +4996,6 @@ func vpnEntryEndpointCandidatesFromHeartbeat(nodeID string, capabilities json.Ra
item["tls_cert_sha256"] = certSHA256
item["peer_cert_sha256"] = certSHA256
}
if apiBaseURL := vpnEntryAPIBaseURL(address); apiBaseURL != "" {
item["api_base_url"] = apiBaseURL
}
out = append(out, item)
}
if len(out) == 0 {
@@ -4943,9 +5014,6 @@ func vpnEntryEndpointCandidatesFromHeartbeat(nodeID string, capabilities json.Ra
"status": "reported",
"source": "node_latest_heartbeat.mesh_endpoint_report.peer_endpoint",
}
if apiBaseURL := vpnEntryAPIBaseURL(address); apiBaseURL != "" {
item["api_base_url"] = apiBaseURL
}
out = append(out, item)
}
}
@@ -5072,17 +5140,6 @@ func heartbeatCapabilityEnabled(capabilities json.RawMessage, name string) bool
}
}
func vpnEntryAPIBaseURL(address string) string {
address = strings.TrimRight(strings.TrimSpace(address), "/")
if address == "" {
return ""
}
if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") {
return ""
}
return address + "/api/v1"
}
func enrichVPNClientEntryEndpointCandidates(connection VPNClientConnection, endpoints map[string][]map[string]any) json.RawMessage {
var cfg map[string]any
if err := json.Unmarshal(connection.ClientConfig, &cfg); err != nil || cfg == nil {
@@ -5346,7 +5403,7 @@ func enrichVPNClientFabricRoute(item VPNClientConnection, preferredEntryNodeID,
entryPool := dedupeStrings(append([]string{}, item.EntryNodeIDs...))
placementPolicy := jsonObjectFromRaw(item.PlacementPolicy)
entrySelector, _ := placementPolicy["entry_selector"].(string)
clientNodeEntry := strings.EqualFold(strings.TrimSpace(entrySelector), "client_node") || placementPolicy["android_node_agent_target"] == true
clientNodeEntry := strings.EqualFold(strings.TrimSpace(entrySelector), "client_node") || placementPolicy["ipv4_ingress_node_target"] == true || placementPolicy["android_node_agent_target"] == true
if len(entryPool) == 0 && !clientNodeEntry {
entryPool = dedupeStrings(append([]string{}, item.AllowedNodeIDs...))
}
@@ -5450,7 +5507,7 @@ func enrichVPNClientFabricRoute(item VPNClientConnection, preferredEntryNodeID,
"queue_policy": "bounded_queue_then_route_failover",
"drop_policy": "drop_only_when_all_routes_unavailable_or_queue_full",
"bulk_and_realtime": "same_packet_path",
"flow_isolation": "hash_by_ip_protocol_and_ports",
"flow_isolation": "opaque_packet_hash_shards",
"target_dataplane": "fabric_farm_entry_to_exit_service_channel",
"temporary_fallback": "none",
},
@@ -5519,8 +5576,8 @@ func vpnFabricRouteCandidates(entryPool, exitPool []string, selectedEntry, selec
"role": role,
"priority": priority,
"status": "candidate",
"source_role": "vpn-client",
"route_scope": "client_node_to_exit_pool",
"source_role": "ipv4-ingress",
"route_scope": "ipv4_ingress_to_egress_pool",
}
if pair.entry != "" {
candidate["entry_node_id"] = pair.entry