Go-based network automation with YANG models, gRPC, Ansible, Terraform, and Kubernetes integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package cni
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/containernetworking/cni/pkg/skel"
|
|
"github.com/containernetworking/cni/pkg/types"
|
|
current "github.com/containernetworking/cni/pkg/types/100"
|
|
)
|
|
|
|
// CmdAdd is called by the container runtime when a pod is created.
|
|
// It creates the net1 interface in the pod's network namespace and programs
|
|
// routes for both overlay (WireGuard) and underlay (VLAN bridge) subnets.
|
|
func CmdAdd(args *skel.CmdArgs) error {
|
|
conf, err := ParseNetConf(args.StdinData)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse config: %w", err)
|
|
}
|
|
|
|
// Load mesh topology for current node state.
|
|
topo, err := loadMeshTopology(conf.MeshConfig)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load mesh topology: %w", err)
|
|
}
|
|
|
|
// Create veth pair and move one end into the pod's network namespace.
|
|
hostVeth, podVeth, err := createVethPair(args.Netns, args.IfName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create veth pair: %w", err)
|
|
}
|
|
|
|
// Attach host-side veth to appropriate backend interfaces.
|
|
if err := attachOverlayRoutes(hostVeth, conf.OverlayRoutes, topo); err != nil {
|
|
return fmt.Errorf("failed to attach overlay routes: %w", err)
|
|
}
|
|
if err := attachUnderlayRoutes(hostVeth, conf.UnderlayRoutes, topo); err != nil {
|
|
return fmt.Errorf("failed to attach underlay routes: %w", err)
|
|
}
|
|
|
|
// Program routes inside the pod's network namespace.
|
|
if err := programPodRoutes(args.Netns, podVeth, conf.OverlayRoutes, conf.UnderlayRoutes); err != nil {
|
|
return fmt.Errorf("failed to program pod routes: %w", err)
|
|
}
|
|
|
|
// Apply SVID-based network policy.
|
|
if err := applySVIDPolicy(args, conf, topo); err != nil {
|
|
return fmt.Errorf("failed to apply SVID policy: %w", err)
|
|
}
|
|
|
|
// Build and return CNI result.
|
|
result := ¤t.Result{
|
|
CNIVersion: conf.CNIVersion,
|
|
Interfaces: []*current.Interface{
|
|
{Name: hostVeth, Sandbox: ""},
|
|
{Name: podVeth, Sandbox: args.Netns},
|
|
},
|
|
}
|
|
return types.PrintResult(result, conf.CNIVersion)
|
|
}
|
|
|
|
// CmdDel is called when a pod is deleted.
|
|
// Tears down the net1 interface and cleans up routes and bridge/tunnel attachments.
|
|
func CmdDel(args *skel.CmdArgs) error {
|
|
conf, err := ParseNetConf(args.StdinData)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse config: %w", err)
|
|
}
|
|
|
|
if err := teardownInterface(args.Netns, args.IfName); err != nil {
|
|
return fmt.Errorf("failed to teardown interface: %w", err)
|
|
}
|
|
|
|
_ = conf // Routes are cleaned up with the interface
|
|
return nil
|
|
}
|
|
|
|
// CmdCheck verifies the net1 interface exists and routes are correct.
|
|
func CmdCheck(args *skel.CmdArgs) error {
|
|
conf, err := ParseNetConf(args.StdinData)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse config: %w", err)
|
|
}
|
|
|
|
if err := verifyInterface(args.Netns, args.IfName); err != nil {
|
|
return fmt.Errorf("interface check failed: %w", err)
|
|
}
|
|
|
|
if err := verifyRoutes(args.Netns, conf.OverlayRoutes, conf.UnderlayRoutes); err != nil {
|
|
return fmt.Errorf("route check failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|