package cni import ( "encoding/json" "fmt" "io" current "github.com/containernetworking/cni/pkg/types/100" ) // Op is the CNI verb the plugin asks the agent to perform. type Op string const ( OpAdd Op = "ADD" OpDel Op = "DEL" OpCheck Op = "CHECK" ) // Request is sent over the unix socket from the CNI plugin to flock-agent. // Field names mirror the kubelet → CNI invocation env vars; the agent uses // these to look up Pod metadata via the informer cache. type Request struct { Op Op `json:"op"` ContainerID string `json:"container_id"` Netns string `json:"netns"` // /proc//ns/net IfName string `json:"ifname"` // typically "eth0" Args string `json:"args"` // raw CNI_ARGS env (K=V;K=V;...) Path string `json:"path"` // CNI_PATH (plugin search path) StdinData []byte `json:"stdin_data"` // raw network configuration JSON } // Response carries either a typed CNI Result or a single error string. // We use a string error (not a Go error) because errors traverse a JSON // boundary; the client converts back to a CNI types.Error. type Response struct { Result *current.Result `json:"result,omitempty"` Error string `json:"error,omitempty"` } // EncodeRequest writes req to w as a single JSON object followed by '\n'. // The newline framing makes the wire-protocol simple to read incrementally // without a length prefix or full-stream-buffering. func EncodeRequest(w io.Writer, req Request) error { b, err := json.Marshal(req) if err != nil { return fmt.Errorf("marshal request: %w", err) } b = append(b, '\n') if _, err := w.Write(b); err != nil { return fmt.Errorf("write request: %w", err) } return nil } // DecodeRequest reads one newline-delimited JSON request from r. func DecodeRequest(r io.Reader) (Request, error) { var req Request dec := json.NewDecoder(r) if err := dec.Decode(&req); err != nil { return Request{}, fmt.Errorf("decode request: %w", err) } return req, nil } // EncodeResponse writes resp to w as a single JSON object followed by '\n'. func EncodeResponse(w io.Writer, resp Response) error { b, err := json.Marshal(resp) if err != nil { return fmt.Errorf("marshal response: %w", err) } b = append(b, '\n') if _, err := w.Write(b); err != nil { return fmt.Errorf("write response: %w", err) } return nil } // DecodeResponse reads one newline-delimited JSON response from r. func DecodeResponse(r io.Reader) (Response, error) { var resp Response dec := json.NewDecoder(r) if err := dec.Decode(&resp); err != nil { return Response{}, fmt.Errorf("decode response: %w", err) } return resp, nil }