util

package
v2.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: GPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	OptionsKeyGeneric = "com.docker.network.generic"
)

Variables

View Source
var (
	// ErrIPAM is every refusal about address allocation: an IPAM driver
	// this plugin will not serve a network for, and the refusals its own
	// IPAM driver makes about a pool or an address (#110).
	//
	// The text no longer names the null driver, and that is the change:
	// two IPAM drivers are supported now, so a message saying otherwise
	// would send an operator to recreate a network that is already
	// correct. Every site that wraps this supplies the specific sentence.
	ErrIPAM = errors.New("this network's address allocation was refused")
	// ErrBridgeRequired indicates a network bridge was not provided for network creation
	ErrBridgeRequired = errors.New("bridge required (mode=bridge)")
	// ErrNotBridge indicates that the provided network interface is not a bridge
	ErrNotBridge = errors.New("network interface is not a bridge")
	// ErrBridgeUsed indicates that a bridge is already in use
	ErrBridgeUsed = errors.New("bridge already in use by Docker")
	// ErrInvalidMode indicates an unsupported value was passed for the `mode` option
	ErrInvalidMode = errors.New("invalid mode (must be 'bridge', 'macvlan' or 'ipvlan')")
	// ErrParentRequired indicates `parent` was not provided when mode=macvlan
	ErrParentRequired = errors.New("parent required (mode=macvlan)")
	// ErrParentInvalid indicates the parent interface cannot host macvlan children
	ErrParentInvalid = errors.New("parent interface is unsuitable for macvlan (bridge or macvlan)")
	// ErrParentDown indicates the parent interface is administratively down
	ErrParentDown = errors.New("parent interface is down")
	// ErrModeMismatch indicates an option that doesn't apply to the chosen mode was set
	ErrModeMismatch = errors.New("option does not apply to selected mode")
	// ErrInvalidServerList indicates dhcp_servers or dhcp_deny_servers
	// could not be parsed, or the two contradict each other
	ErrInvalidServerList = errors.New("invalid DHCP server list")
	// ErrMACAddress indicates an invalid MAC address
	ErrMACAddress = errors.New("invalid MAC address")
	// ErrNoLease indicates a DHCP lease was not obtained from dhcpcd
	ErrNoLease = errors.New("no lease was acquired")

	// ErrNoHint indicates missing state from the CreateEndpoint stage in Join
	ErrNoHint = errors.New("missing CreateEndpoint hints")
	// ErrNotVEth indicates a host link was unexpectedly not a veth interface
	ErrNotVEth = errors.New("host link is not a veth interface")
	// ErrNoContainer indicates a container was unexpectedly not found
	ErrNoContainer = errors.New("couldn't find container by endpoint on the network")
	// ErrNoSandbox indicates missing state from the Join stage
	ErrNoSandbox = errors.New("missing joined endpoint state")
)

Functions

func AwaitCondition

func AwaitCondition(ctx context.Context, cond func() (bool, error), interval time.Duration) error

AwaitCondition polls cond every interval until it returns ok=true, an error, or ctx is cancelled. The poll runs synchronously in the caller's goroutine: a previous async-poller form leaked a goroutine on every ctx-cancel because it kept calling cond forever (typically Docker NetworkInspect, ~10/s/leaked-goroutine). cond is expected to be reasonably fast or to honor ctx itself; we don't try to interrupt it.

func AwaitContainerInspect

func AwaitContainerInspect(ctx context.Context, docker ContainerInspector, id string, interval time.Duration) (container.InspectResponse, error)

AwaitContainerInspect polls docker.ContainerInspect until it succeeds, ctx is cancelled, or interval-paced retries exhaust. Synchronous for the same reason as AwaitLinkByIndex — the previous async form leaked a poller goroutine on ctx-cancel that kept hitting the Docker API forever.

"No such container" ends the wait immediately instead of being retried. Polling for a container that has been removed can only ever end in the deadline, and callers then read that deadline as "the daemon was slow" when what actually happened is "the container is gone". Those need opposite responses: one is a fault worth counting, the other is an ordinary short-lived container. Retrying an absence spent the whole budget converting the second into the first — nine to twelve times per integration run (#401).

A NotFound arriving here means removed, not "not yet": every caller resolves the container ID from the daemon first, so it existed moments ago. The error is returned with its chain intact so callers can classify with cerrdefs.IsNotFound.

Other errors are still retried, and the last one is reported alongside the deadline — the same contract AwaitLinkByIndex and AwaitLinkByIndex already keep. Discarding it here was why a Join timeout said only "context deadline exceeded" while its sibling failures named a missing file.

func AwaitLinkByIndex

func AwaitLinkByIndex(ctx context.Context, handle *netlink.Handle, index int, interval time.Duration) (netlink.Link, error)

AwaitLinkByIndex polls for a netlink Link by index until it appears, ctx is cancelled, or interval-paced retries exhaust. Synchronous because the async form leaked a goroutine per call; it surfaces the last attempt's error alongside the deadline because a bare "context deadline exceeded" hid a persistent failure in production for weeks (#317).

func DumpResult

func DumpResult[T any](v []T, err error) ([]T, error)

DumpResult is what a netlink dump call returns, with the one error that is not a failure removed.

In vishvananda/netlink v1.3.1 every dump-style call — LinkList, AddrList, RouteList and their filtered and *WithOptions forms — returns ErrDumpInterrupted TOGETHER WITH A USABLE RESULT SET. link_linux.go:2419-2436 bails early only on an error that is not the sentinel; otherwise it parses the messages and hands them back alongside it. The sentinel means the kernel set NLM_F_DUMP_INTR because the table changed mid-dump, which is what a suite creating and tearing down macvlan children generates by design.

Treating it as fatal cost the arm64 lane a red on the v1.8.0-rc2 tag (#802) and is the fail-open half of the mode-collision guard in childLinkKind. Every OTHER error is returned unchanged: a helper that swallowed them would turn a real netlink failure into an empty result set, which is the same blindness pointing the other way.

Used as `util.DumpResult(netlink.LinkList())` — the dump call's two results are the two parameters — so no call site has to spell the sentinel, and scripts/check-netlink-dump-errors.sh refuses a dump call that does not go through here.

func ErrToStatus

func ErrToStatus(err error) int

ErrToStatus maps a sentinel error to its HTTP status. Validation errors (caller-supplied bad input) produce 400. Upstream-DHCP and retryable Docker-state-transition errors produce 502 / 503 / 409 so the wire shape is meaningful to non-libnetwork consumers; the libnetwork integration treats all 5xx the same so this is purely a clarity win for direct API users / logs / dashboards.

Anything not enumerated here falls through to 500 — those are either internal plumbing failures (netlink, fs) or unexpected daemon errors, where 500 is the honest answer.

func JSONErrResponse

func JSONErrResponse(w http.ResponseWriter, err error, statusCode int)

JSONErrResponse Sends an `error` as a JSON object with a `message` property. Logs at a level matching the HTTP status:

  • 5xx -> Error (we did something wrong)
  • 4xx -> Warn (caller did something wrong; not actionable for us)
  • other -> Info

A torrent of 4xx from a misconfigured client used to land at ERROR, drowning real failures (I-12 in the 2026-05-05 review).

func JSONResponse

func JSONResponse(w http.ResponseWriter, v interface{}, statusCode int)

JSONResponse Sends a JSON payload in response to a HTTP request. The payload is encoded into a buffer first so that, on encoding failure, we can still send a clean HTTP 500 instead of a garbled response with a half-flushed body and a no-op second WriteHeader call.

func ParseJSONOrErrorResponse

func ParseJSONOrErrorResponse(v interface{}, w http.ResponseWriter, r *http.Request) error

ParseJSONOrErrorResponse decodes the request body as JSON into v. On failure it ALSO writes a 400 JSON error response to w; the caller is expected to early-return on a non-nil error and not touch w again. The verbose name is deliberate: the prior name (ParseJSONBody) read as a pure parse, but the function quietly took over response writing — a future caller writing the obvious-looking

if err := ParseJSONBody(&req, w, r); err != nil {
    JSONErrResponse(w, err, ...); return
}

would double-write headers. This name makes the response-writing side-effect impossible to overlook at the call site.

func WriteAccessLog

func WriteAccessLog(w io.Writer, params handlers.LogFormatterParams)

Types

type ContainerInspector

type ContainerInspector interface {
	ContainerInspect(ctx context.Context, id string) (container.InspectResponse, error)
}

ContainerInspector is the one Docker-client method AwaitContainerInspect needs. Taking an interface (not the concrete *client.Client) lets callers inject a fake in tests; the real client satisfies it as-is.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL