39ede9130b
Build flock Image / build (push) Has been cancelled
New pkg/agent/netpol implementing standard networking.k8s.io/v1 NetworkPolicy. Pipeline: pods + policies + namespaces → Translate → Render → Apply Supports ingress + egress, all three peer types (podSelector, namespaceSelector, ipBlock with except), numeric ports + port ranges, default-deny semantics derived from PolicyTypes (or inferred from non-empty Spec.Egress when unset). Apply path is `nft -f -` shell-out — single transaction, atomic, kernel guarantees partial-failure rollback. Idempotent dedup via last-applied script. Reconcile triggers: informer events, 30s self-heal tick, every CNI ADD/DEL. Verified against the three live cluster NetPols (calico-apiserver, remote-proxies/lodge-home-assistant, storage/garage-admin-restrict). Fuzz target stitches Translate + Render with random selector and peer inputs; 21 unit tests cover the policy semantics. Named ports skip with a warn — deferred until kubelet exposes them in a form that doesn't require shadowing pod state. Dockerfile: + nftables. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
57 lines
1.3 KiB
Go
57 lines
1.3 KiB
Go
package agent
|
|
|
|
import (
|
|
"net"
|
|
|
|
"code.fritzlab.net/fritzlab/flock/pkg/agent/netpol"
|
|
)
|
|
|
|
// collectLocalPods bridges the agent's allocation store + pod informer
|
|
// cache into the netpol-package input shape. It returns one Pod per
|
|
// committed allocation that has a matching pod in the informer cache;
|
|
// allocations whose pod was just deleted (DEL race) are skipped.
|
|
//
|
|
// Called on every netpol reconcile pass, so it must be cheap. The work
|
|
// here is O(allocations) and reads from in-memory maps only.
|
|
func collectLocalPods(store *Store, pods *PodCache) []netpol.Pod {
|
|
allocs := store.Snapshot()
|
|
out := make([]netpol.Pod, 0, len(allocs))
|
|
for _, a := range allocs {
|
|
if a.State != StateCommitted {
|
|
continue
|
|
}
|
|
pod, ok := pods.Get(a.Namespace, a.PodName)
|
|
if !ok {
|
|
// Pod evicted but DEL hasn't fired yet; nothing to enforce.
|
|
continue
|
|
}
|
|
ips := allocationIPs(a)
|
|
if len(ips) == 0 {
|
|
continue
|
|
}
|
|
out = append(out, netpol.Pod{
|
|
Namespace: a.Namespace,
|
|
Name: a.PodName,
|
|
Labels: pod.Labels,
|
|
HostIface: HostIfaceName(a.ContainerID),
|
|
IPs: ips,
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
func allocationIPs(a Allocation) []net.IP {
|
|
var out []net.IP
|
|
if a.IP6 != "" {
|
|
if ip := net.ParseIP(a.IP6); ip != nil {
|
|
out = append(out, ip)
|
|
}
|
|
}
|
|
if a.IP4 != "" {
|
|
if ip := net.ParseIP(a.IP4); ip != nil {
|
|
out = append(out, ip)
|
|
}
|
|
}
|
|
return out
|
|
}
|