summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/rootless-cni-infra/Containerfile36
-rw-r--r--contrib/rootless-cni-infra/README.md25
-rwxr-xr-xcontrib/rootless-cni-infra/rootless-cni-infra181
-rw-r--r--libpod/networking_linux.go12
-rw-r--r--libpod/rootless_cni_linux.go372
5 files changed, 12 insertions, 614 deletions
diff --git a/contrib/rootless-cni-infra/Containerfile b/contrib/rootless-cni-infra/Containerfile
deleted file mode 100644
index 4324f39d2..000000000
--- a/contrib/rootless-cni-infra/Containerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-ARG GOLANG_VERSION=1.15
-ARG ALPINE_VERSION=3.12
-ARG CNI_VERSION=v0.8.0
-ARG CNI_PLUGINS_VERSION=v0.8.7
-ARG DNSNAME_VERSION=v1.1.1
-
-FROM golang:${GOLANG_VERSION}-alpine${ALPINE_VERSION} AS golang-base
-RUN apk add --no-cache git
-
-FROM golang-base AS cnitool
-RUN git clone https://github.com/containernetworking/cni /go/src/github.com/containernetworking/cni
-WORKDIR /go/src/github.com/containernetworking/cni
-ARG CNI_VERSION
-RUN git checkout ${CNI_VERSION}
-RUN go build -o /cnitool ./cnitool
-
-FROM golang-base AS dnsname
-RUN git clone https://github.com/containers/dnsname /go/src/github.com/containers/dnsname
-WORKDIR /go/src/github.com/containers/dnsname
-ARG DNSNAME_VERSION
-RUN git checkout ${DNSNAME_VERSION}
-RUN go build -o /dnsname ./plugins/meta/dnsname
-
-FROM alpine:${ALPINE_VERSION}
-RUN apk add --no-cache curl dnsmasq iptables ip6tables iproute2
-ARG TARGETARCH
-ARG CNI_PLUGINS_VERSION
-RUN mkdir -p /opt/cni/bin && \
- curl -fsSL https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${TARGETARCH}-${CNI_PLUGINS_VERSION}.tgz | tar xz -C /opt/cni/bin
-COPY --from=cnitool /cnitool /usr/local/bin
-COPY --from=dnsname /dnsname /opt/cni/bin
-COPY rootless-cni-infra /usr/local/bin
-ENV CNI_PATH=/opt/cni/bin
-CMD ["sleep", "infinity"]
-
-ENV ROOTLESS_CNI_INFRA_VERSION=5
diff --git a/contrib/rootless-cni-infra/README.md b/contrib/rootless-cni-infra/README.md
deleted file mode 100644
index c43b4cf49..000000000
--- a/contrib/rootless-cni-infra/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# rootless-cni-infra
-
-Infra container for CNI-in-slirp4netns.
-
-## How it works
-
-When a CNI network is specified for `podman run` in rootless mode, Podman launches the `rootless-cni-infra` container to execute CNI plugins inside slirp4netns.
-
-The infra container is created per user, by executing an equivalent of:
-`podman run -d --name rootless-cni-infra --pid=host --privileged -v $HOME/.config/cni/net.d:/etc/cni/net.d rootless-cni-infra`.
-The infra container is automatically deleted when no CNI network is in use.
-
-Podman then allocates a CNI netns in the infra container, by executing an equivalent of:
-`podman exec rootless-cni-infra rootless-cni-infra alloc $CONTAINER_ID $NETWORK_NAME $POD_NAME`.
-
-The allocated netns is deallocated when the container is being removed, by executing an equivalent of:
-`podman exec rootless-cni-infra rootless-cni-infra dealloc $CONTAINER_ID $NETWORK_NAME`.
-
-The container images live on `quay.io/libpod/rootless-cni-infra`. The tags have the format `$version-$architecture`. Please make sure to increase the version number in the Containerfile (i.e., `ROOTLESS_CNI_INFRA_VERSION`) when applying changes to this directory. After committing the changes, upload the image(s) with the corresponding tag.
-
-## Directory layout
-
-* `/run/rootless-cni-infra/${CONTAINER_ID}/pid`: PID of the `sleep infinity` process that corresponds to the allocated netns
-* `/run/rootless-cni-infra/${CONTAINER_ID}/attached/${NETWORK_NAME}`: CNI result
-* `/run/rootless-cni-infra/${CONTAINER_ID}/attached-args/${NETWORK_NAME}`: CNI args
diff --git a/contrib/rootless-cni-infra/rootless-cni-infra b/contrib/rootless-cni-infra/rootless-cni-infra
deleted file mode 100755
index cceb8d817..000000000
--- a/contrib/rootless-cni-infra/rootless-cni-infra
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/bin/sh
-set -eu
-
-ARG0="$0"
-BASE="/run/rootless-cni-infra"
-
-wait_unshare_net() {
- pid="$1"
- # NOTE: busybox shell doesn't support the `for ((i=0; i < $MAX; i++)); do foo; done` statement
- i=0
- while :; do
- if [ "$(readlink /proc/self/ns/net)" != "$(readlink /proc/${pid}/ns/net)" ]; then
- break
- fi
- sleep 0.1
- if [ $i -ge 10 ]; then
- echo >&2 "/proc/${pid}/ns/net cannot be unshared"
- exit 1
- fi
- i=$((i + 1))
- done
-}
-
-# CLI subcommand: "alloc $CONTAINER_ID $NETWORK_NAME $POD_NAME $IP $MAC $CAP_ARGS"
-cmd_entrypoint_alloc() {
- if [ "$#" -ne 6 ]; then
- echo >&2 "Usage: $ARG0 alloc CONTAINER_ID NETWORK_NAME POD_NAME IP MAC CAP_ARGS"
- exit 1
- fi
-
- ID="$1"
- NET="$2"
- K8S_POD_NAME="$3"
- IP="$4"
- MAC="$5"
- CAP_ARGS="$6"
-
- dir="${BASE}/${ID}"
- mkdir -p "${dir}/attached" "${dir}/attached-args"
-
- pid=""
- if [ -f "${dir}/pid" ]; then
- pid=$(cat "${dir}/pid")
- else
- unshare -n sleep infinity &
- pid="$!"
- wait_unshare_net "${pid}"
- echo "${pid}" >"${dir}/pid"
- nsenter -t "${pid}" -n ip link set lo up
- fi
- CNI_ARGS="IgnoreUnknown=1;K8S_POD_NAME=${K8S_POD_NAME}"
- if [ "$IP" ]; then
- CNI_ARGS="$CNI_ARGS;IP=${IP}"
- fi
- if [ "$MAC" ]; then
- CNI_ARGS="$CNI_ARGS;MAC=${MAC}"
- fi
- if [ "$CAP_ARGS" ]; then
- CAP_ARGS="$CAP_ARGS"
- fi
- nwcount=$(find "${dir}/attached" -type f | wc -l)
- CNI_IFNAME="eth${nwcount}"
- export CNI_ARGS CNI_IFNAME CAP_ARGS
- cnitool add "${NET}" "/proc/${pid}/ns/net" >"${dir}/attached/${NET}"
- echo "${CNI_ARGS}" >"${dir}/attached-args/${NET}"
-
- # return the result
- ns="/proc/${pid}/ns/net"
- echo "{\"ns\":\"${ns}\"}"
-}
-
-# CLI subcommand: "dealloc $CONTAINER_ID $NETWORK_NAME"
-cmd_entrypoint_dealloc() {
- if [ "$#" -ne 2 ]; then
- echo >&2 "Usage: $ARG0 dealloc CONTAINER_ID NETWORK_NAME"
- exit 1
- fi
-
- ID=$1
- NET=$2
-
- dir="${BASE}/${ID}"
- if [ ! -f "${dir}/pid" ]; then
- exit 0
- fi
- pid=$(cat "${dir}/pid")
- if [ -f "${dir}/attached-args/${NET}" ]; then
- CNI_ARGS=$(cat "${dir}/attached-args/${NET}")
- export CNI_ARGS
- fi
- cnitool del "${NET}" "/proc/${pid}/ns/net"
- rm -f "${dir}/attached/${NET}" "${dir}/attached-args/${NET}"
-
- nwcount=$(find "${dir}/attached" -type f | wc -l)
- if [ "${nwcount}" = 0 ]; then
- kill -9 "${pid}"
- rm -rf "${dir}"
- fi
-
- # return empty json
- echo "{}"
-}
-
-# CLI subcommand: "is-idle"
-cmd_entrypoint_is_idle() {
- if [ ! -d ${BASE} ]; then
- echo '{"idle": true}'
- elif [ -z "$(ls -1 ${BASE})" ]; then
- echo '{"idle": true}'
- else
- echo '{"idle": false}'
- fi
-}
-
-# CLI subcommand: "print-cni-result $CONTAINER_ID $NETWORK_NAME"
-cmd_entrypoint_print_cni_result() {
- if [ "$#" -ne 2 ]; then
- echo >&2 "Usage: $ARG0 print-cni-result CONTAINER_ID NETWORK_NAME"
- exit 1
- fi
-
- ID=$1
- NET=$2
-
- # the result shall be CNI JSON
- cat "${BASE}/${ID}/attached/${NET}"
-}
-
-# CLI subcommand: "print-netns-path $CONTAINER_ID"
-cmd_entrypoint_print_netns_path() {
- if [ "$#" -ne 1 ]; then
- echo >&2 "Usage: $ARG0 print-netns-path CONTAINER_ID"
- exit 1
- fi
-
- ID=$1
-
- pid=$(cat "${BASE}/${ID}/pid")
- path="/proc/${pid}/ns/net"
-
- # return the result
- echo "{\"path\":\"${path}\"}"
-}
-
-# CLI subcommand: "help"
-cmd_entrypoint_help() {
- echo "Usage: ${ARG0} COMMAND"
- echo
- echo "Rootless CNI Infra container"
- echo
- echo "Commands:"
- echo " alloc Allocate a netns"
- echo " dealloc Deallocate a netns"
- echo " is-idle Print whether the infra container is idle"
- echo " print-cni-result Print CNI result"
- echo " print-netns-path Print netns path"
- echo " help Print help"
- echo " version Print version"
-}
-
-# CLI subcommand: "version"
-cmd_entrypoint_version() {
- echo "{\"version\": \"${ROOTLESS_CNI_INFRA_VERSION}\"}"
-}
-
-# parse args
-command="${1:-}"
-if [ -z "$command" ]; then
- echo >&2 "No command was specified. Run \`${ARG0} help\` to see the usage."
- exit 1
-fi
-
-command_func=$(echo "cmd_entrypoint_${command}" | sed -e "s/-/_/g")
-if ! command -v "${command_func}" >/dev/null 2>&1; then
- echo >&2 "Unknown command: ${command}. Run \`${ARG0} help\` to see the usage."
- exit 1
-fi
-
-# start the command func
-shift
-"${command_func}" "$@"
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index d927b17d8..2734f7759 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -338,6 +338,18 @@ func (r *Runtime) setUpOCICNIPod(podNetwork ocicni.PodNetwork) ([]ocicni.NetResu
return results, err
}
+// getCNIPodName return the pod name (hostname) used by CNI and the dnsname plugin.
+// If we are in the pod network namespace use the pod name otherwise the container name
+func getCNIPodName(c *Container) string {
+ if c.config.NetMode.IsPod() || c.IsInfra() {
+ pod, err := c.runtime.GetPod(c.PodID())
+ if err == nil {
+ return pod.Name()
+ }
+ }
+ return c.Name()
+}
+
// Create and configure a new network namespace for a container
func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Result, error) {
var requestedIP net.IP
diff --git a/libpod/rootless_cni_linux.go b/libpod/rootless_cni_linux.go
deleted file mode 100644
index df690e914..000000000
--- a/libpod/rootless_cni_linux.go
+++ /dev/null
@@ -1,372 +0,0 @@
-// +build linux
-
-package libpod
-
-import (
- "bytes"
- "context"
- "io"
- "path/filepath"
- "runtime"
-
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
- "github.com/containernetworking/plugins/pkg/ns"
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/image"
- "github.com/containers/podman/v3/pkg/env"
- "github.com/containers/podman/v3/pkg/util"
- "github.com/containers/storage/pkg/lockfile"
- "github.com/hashicorp/go-multierror"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-// Built from ../contrib/rootless-cni-infra.
-var rootlessCNIInfraImage = map[string]string{
- "amd64": "quay.io/libpod/rootless-cni-infra@sha256:adf352454666f7ce9ca3e1098448b5ee18f89c4516471ec99447ec9ece917f36", // 5-amd64
-}
-
-const (
- rootlessCNIInfraContainerNamespace = "podman-system"
- rootlessCNIInfraContainerName = "rootless-cni-infra"
-)
-
-// AllocRootlessCNI allocates a CNI netns inside the rootless CNI infra container.
-// Locks "rootless-cni-infra.lck".
-//
-// When the infra container is not running, it is created.
-//
-// AllocRootlessCNI does not lock c. c should be already locked.
-func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.Result, error) {
- networks, _, err := c.networks()
- if err != nil {
- return nil, nil, err
- }
- if len(networks) == 0 {
- return nil, nil, errors.New("rootless CNI networking requires that the container has joined at least one CNI network")
- }
- l, err := getRootlessCNIInfraLock(c.runtime)
- if err != nil {
- return nil, nil, err
- }
- l.Lock()
- defer l.Unlock()
- infra, err := ensureRootlessCNIInfraContainerRunning(ctx, c.runtime)
- if err != nil {
- return nil, nil, err
- }
- k8sPodName := getCNIPodName(c) // passed to CNI as K8S_POD_NAME
- ip := ""
- if c.config.StaticIP != nil {
- ip = c.config.StaticIP.String()
- }
- mac := ""
- if c.config.StaticMAC != nil {
- mac = c.config.StaticMAC.String()
- }
- aliases, err := c.runtime.state.GetAllNetworkAliases(c)
- if err != nil {
- return nil, nil, err
- }
- capArgs := ""
- // add network aliases json encoded as capabilityArgs for cni
- if len(aliases) > 0 {
- capabilityArgs := make(map[string]interface{})
- capabilityArgs["aliases"] = aliases
- b, err := json.Marshal(capabilityArgs)
- if err != nil {
- return nil, nil, err
- }
- capArgs = string(b)
- }
-
- cniResults := make([]*cnitypes.Result, len(networks))
- for i, nw := range networks {
- cniRes, err := rootlessCNIInfraCallAlloc(infra, c.ID(), nw, k8sPodName, ip, mac, capArgs)
- if err != nil {
- return nil, nil, err
- }
- cniResults[i] = cniRes
- }
- nsObj, err := rootlessCNIInfraGetNS(infra, c.ID())
- if err != nil {
- return nil, nil, err
- }
- logrus.Debugf("rootless CNI: container %q will join %q", c.ID(), nsObj.Path())
- return nsObj, cniResults, nil
-}
-
-// DeallocRootlessCNI deallocates a CNI netns inside the rootless CNI infra container.
-// Locks "rootless-cni-infra.lck".
-//
-// When the infra container is no longer needed, it is removed.
-//
-// DeallocRootlessCNI does not lock c. c should be already locked.
-func DeallocRootlessCNI(ctx context.Context, c *Container) error {
- networks, _, err := c.networks()
- if err != nil {
- return err
- }
- if len(networks) == 0 {
- return errors.New("rootless CNI networking requires that the container has joined at least one CNI network")
- }
- l, err := getRootlessCNIInfraLock(c.runtime)
- if err != nil {
- return err
- }
- l.Lock()
- defer l.Unlock()
- infra, _ := getRootlessCNIInfraContainer(c.runtime)
- if infra == nil {
- return nil
- }
- var errs *multierror.Error
- for _, nw := range networks {
- err := rootlessCNIInfraCallDealloc(infra, c.ID(), nw)
- if err != nil {
- errs = multierror.Append(errs, err)
- }
- }
- if isIdle, err := rootlessCNIInfraIsIdle(infra); isIdle || err != nil {
- if err != nil {
- logrus.Warn(err)
- }
- logrus.Debugf("rootless CNI: removing infra container %q", infra.ID())
- infra.lock.Lock()
- defer infra.lock.Unlock()
- if err := c.runtime.removeContainer(ctx, infra, true, false, true); err != nil {
- return err
- }
- logrus.Debugf("rootless CNI: removed infra container %q", infra.ID())
- }
- return errs.ErrorOrNil()
-}
-
-func getRootlessCNIInfraLock(r *Runtime) (lockfile.Locker, error) {
- fname := filepath.Join(r.config.Engine.TmpDir, "rootless-cni-infra.lck")
- return lockfile.GetLockfile(fname)
-}
-
-// getCNIPodName return the pod name (hostname) used by CNI and the dnsname plugin.
-// If we are in the pod network namespace use the pod name otherwise the container name
-func getCNIPodName(c *Container) string {
- if c.config.NetMode.IsPod() || c.IsInfra() {
- pod, err := c.runtime.GetPod(c.PodID())
- if err == nil {
- return pod.Name()
- }
- }
- return c.Name()
-}
-
-func rootlessCNIInfraCallAlloc(infra *Container, id, nw, k8sPodName, ip, mac, capArgs string) (*cnitypes.Result, error) {
- logrus.Debugf("rootless CNI: alloc %q, %q, %q, %q, %q, %q", id, nw, k8sPodName, ip, mac, capArgs)
- var err error
-
- _, err = rootlessCNIInfraExec(infra, "alloc", id, nw, k8sPodName, ip, mac, capArgs)
- if err != nil {
- return nil, err
- }
- cniResStr, err := rootlessCNIInfraExec(infra, "print-cni-result", id, nw)
- if err != nil {
- return nil, err
- }
- var cniRes cnitypes.Result
- if err := json.Unmarshal([]byte(cniResStr), &cniRes); err != nil {
- return nil, errors.Wrapf(err, "unmarshaling as cnitypes.Result: %q", cniResStr)
- }
- return &cniRes, nil
-}
-
-func rootlessCNIInfraCallDealloc(infra *Container, id, nw string) error {
- logrus.Debugf("rootless CNI: dealloc %q, %q", id, nw)
- _, err := rootlessCNIInfraExec(infra, "dealloc", id, nw)
- return err
-}
-
-func rootlessCNIInfraIsIdle(infra *Container) (bool, error) {
- type isIdle struct {
- Idle bool `json:"idle"`
- }
- resStr, err := rootlessCNIInfraExec(infra, "is-idle")
- if err != nil {
- return false, err
- }
- var res isIdle
- if err := json.Unmarshal([]byte(resStr), &res); err != nil {
- return false, errors.Wrapf(err, "unmarshaling as isIdle: %q", resStr)
- }
- return res.Idle, nil
-}
-
-func rootlessCNIInfraGetNS(infra *Container, id string) (ns.NetNS, error) {
- type printNetnsPath struct {
- Path string `json:"path"`
- }
- resStr, err := rootlessCNIInfraExec(infra, "print-netns-path", id)
- if err != nil {
- return nil, err
- }
- var res printNetnsPath
- if err := json.Unmarshal([]byte(resStr), &res); err != nil {
- return nil, errors.Wrapf(err, "unmarshaling as printNetnsPath: %q", resStr)
- }
- nsObj, err := ns.GetNS(res.Path)
- if err != nil {
- return nil, err
- }
- return nsObj, nil
-}
-
-func getRootlessCNIInfraContainer(r *Runtime) (*Container, error) {
- containers, err := r.GetContainersWithoutLock(func(c *Container) bool {
- return c.Namespace() == rootlessCNIInfraContainerNamespace &&
- c.Name() == rootlessCNIInfraContainerName
- })
- if err != nil {
- return nil, err
- }
- if len(containers) == 0 {
- return nil, nil
- }
- return containers[0], nil
-}
-
-func ensureRootlessCNIInfraContainerRunning(ctx context.Context, r *Runtime) (*Container, error) {
- c, err := getRootlessCNIInfraContainer(r)
- if err != nil {
- return nil, err
- }
- if c == nil {
- return startRootlessCNIInfraContainer(ctx, r)
- }
- st, err := c.ContainerState()
- if err != nil {
- return nil, err
- }
- if st.State == define.ContainerStateRunning {
- logrus.Debugf("rootless CNI: infra container %q is already running", c.ID())
- return c, nil
- }
- logrus.Debugf("rootless CNI: infra container %q is %q, being started", c.ID(), st.State)
- if err := c.initAndStart(ctx); err != nil {
- return nil, err
- }
- logrus.Debugf("rootless CNI: infra container %q is running", c.ID())
- return c, nil
-}
-
-func startRootlessCNIInfraContainer(ctx context.Context, r *Runtime) (*Container, error) {
- imageName, ok := rootlessCNIInfraImage[runtime.GOARCH]
- if !ok {
- return nil, errors.Errorf("cannot find rootless-podman-network-sandbox image for %s", runtime.GOARCH)
- }
- logrus.Debugf("rootless CNI: ensuring image %q to exist", imageName)
- newImage, err := r.ImageRuntime().New(ctx, imageName, "", "", nil, nil,
- image.SigningOptions{}, nil, util.PullImageMissing, nil)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("rootless CNI: image %q is ready", imageName)
-
- g, err := generate.New("linux")
- if err != nil {
- return nil, err
- }
- g.SetupPrivileged(true)
- // Set --pid=host for ease of propagating "/proc/PID/ns/net" string
- if err := g.RemoveLinuxNamespace(string(spec.PIDNamespace)); err != nil {
- return nil, err
- }
- g.RemoveMount("/proc")
- procMount := spec.Mount{
- Destination: "/proc",
- Type: "bind",
- Source: "/proc",
- Options: []string{"rbind", "nosuid", "noexec", "nodev"},
- }
- g.AddMount(procMount)
- // Mount CNI networks
- etcCNINetD := spec.Mount{
- Destination: "/etc/cni/net.d",
- Type: "bind",
- Source: r.config.Network.NetworkConfigDir,
- Options: []string{"ro", "bind"},
- }
- g.AddMount(etcCNINetD)
-
- inspectData, err := newImage.Inspect(ctx)
- if err != nil {
- return nil, err
- }
- imageEnv, err := env.ParseSlice(inspectData.Config.Env)
- if err != nil {
- return nil, err
- }
- for k, v := range imageEnv {
- g.AddProcessEnv(k, v)
- }
- if len(inspectData.Config.Cmd) == 0 {
- return nil, errors.Errorf("rootless CNI infra image %q has no command specified", imageName)
- }
- g.SetProcessArgs(inspectData.Config.Cmd)
-
- var options []CtrCreateOption
- options = append(options, WithRootFSFromImage(newImage.ID(), imageName, imageName))
- options = append(options, WithCtrNamespace(rootlessCNIInfraContainerNamespace))
- options = append(options, WithName(rootlessCNIInfraContainerName))
- options = append(options, WithPrivileged(true))
- options = append(options, WithSecLabels([]string{"disable"}))
- options = append(options, WithRestartPolicy("always"))
- options = append(options, WithNetNS(nil, false, "slirp4netns", nil))
- c, err := r.NewContainer(ctx, g.Config, options...)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("rootless CNI infra container %q is created, now being started", c.ID())
- if err := c.initAndStart(ctx); err != nil {
- return nil, err
- }
- logrus.Debugf("rootless CNI: infra container %q is running", c.ID())
-
- return c, nil
-}
-
-func rootlessCNIInfraExec(c *Container, args ...string) (string, error) {
- cmd := "rootless-cni-infra"
- var (
- outB bytes.Buffer
- errB bytes.Buffer
- streams define.AttachStreams
- config ExecConfig
- )
- streams.OutputStream = &nopWriteCloser{Writer: &outB}
- streams.ErrorStream = &nopWriteCloser{Writer: &errB}
- streams.AttachOutput = true
- streams.AttachError = true
- config.Command = append([]string{cmd}, args...)
- config.Privileged = true
- logrus.Debugf("rootlessCNIInfraExec: c.ID()=%s, config=%+v, streams=%v, begin",
- c.ID(), config, streams)
- code, err := c.Exec(&config, &streams, nil)
- logrus.Debugf("rootlessCNIInfraExec: c.ID()=%s, config=%+v, streams=%v, end (code=%d, err=%v)",
- c.ID(), config, streams, code, err)
- if err != nil {
- return "", err
- }
- if code != 0 {
- return "", errors.Errorf("command %s %v in container %s failed with status %d, stdout=%q, stderr=%q",
- cmd, args, c.ID(), code, outB.String(), errB.String())
- }
- return outB.String(), nil
-}
-
-type nopWriteCloser struct {
- io.Writer
-}
-
-func (nwc *nopWriteCloser) Close() error {
- return nil
-}