diff --git a/client/clienttest/runtime.go b/client/clienttest/runtime.go index ede91d6..c8857e3 100644 --- a/client/clienttest/runtime.go +++ b/client/clienttest/runtime.go @@ -24,6 +24,7 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" @@ -59,7 +60,7 @@ func (r *runtime) RecommendedRuntimeInfo(context.Context, *model.Container) *con return &containers.RuntimeInfo{} } -func (r *runtime) NodeExecute(ctx context.Context, name string, commands ...string) error { +func (r *runtime) NodeExecute(ctx context.Context, _ cio.Creator, name string, commands ...string) error { if len(commands) == 0 { return nil } @@ -160,7 +161,7 @@ func (r *runtime) GetContainerStatus(ctx context.Context, containerID string) (c return client.ContainerStatus{Status: containerd.Status{Status: containerd.Running}}, nil } -func (r *runtime) ExecCommand(ctx context.Context, containerID string, commands []string) (*containerd.ExitStatus, error) { +func (r *runtime) ExecCommand(ctx context.Context, _ cio.Creator, containerID string, commands []string) (*containerd.ExitStatus, error) { _, ok := r.containers[containerID] if !ok { return nil, fmt.Errorf("container %s not found", containerID) diff --git a/client/interface.go b/client/interface.go index 2706a86..5d1b6ad 100644 --- a/client/interface.go +++ b/client/interface.go @@ -21,6 +21,7 @@ import ( "io" "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/images" "github.com/containerd/containerd/platforms" @@ -44,7 +45,7 @@ type Runtime interface { // Namespace of the current runtime in Namespace() string // NodeExecute execute commands on the runtime node - NodeExecute(ctx context.Context, name string, commands ...string) error + NodeExecute(ctx context.Context, ioc cio.Creator, name string, commands ...string) error // ConfigRuntime config container runtime ConfigRuntime(ctx context.Context) error // RemoveNamespace delete runtime namespace @@ -108,5 +109,5 @@ type ContainerManager interface { GetContainerStatus(ctx context.Context, containerID string) (ContainerStatus, error) // ExecCommand exec giving commands and return result - ExecCommand(ctx context.Context, containerID string, commands []string) (*containerd.ExitStatus, error) + ExecCommand(ctx context.Context, ioc cio.Creator, containerID string, commands []string) (*containerd.ExitStatus, error) } diff --git a/client/runtime.go b/client/runtime.go index e60e17d..b854fb4 100644 --- a/client/runtime.go +++ b/client/runtime.go @@ -162,8 +162,8 @@ func (r *runtime) Platform() platforms.MatchComparer { return r.platform } func (r *runtime) ContainerdClient() *containerd.Client { return r.client } func (r *runtime) Namespace() string { return r.namespace } -func (r *runtime) NodeExecute(ctx context.Context, name string, commands ...string) error { - return r.execHostCommand(ctx, name, commands...) +func (r *runtime) NodeExecute(ctx context.Context, ioc cio.Creator, name string, commands ...string) error { + return r.execHostCommand(ctx, ioc, name, commands...) } func (r *runtime) ConfigRuntime(ctx context.Context) error { @@ -414,8 +414,9 @@ func (r *runtime) GetContainerStatus(ctx context.Context, containerID string) (C }, nil } -func (r *runtime) ExecCommand(ctx context.Context, containerID string, commands []string) (*containerd.ExitStatus, error) { +func (r *runtime) ExecCommand(ctx context.Context, ioc cio.Creator, containerID string, commands []string) (*containerd.ExitStatus, error) { ctx = namespaces.WithNamespace(ctx, r.namespace) + ioc = lo.If(ioc != nil, ioc).Else(cio.NullIO) c, err := r.client.LoadContainer(ctx, containerID) if err != nil { @@ -437,7 +438,7 @@ func (r *runtime) ExecCommand(ctx context.Context, containerID string, commands progressSpec.Terminal = false progressSpec.Args = commands - progress, err := task.Exec(ctx, taskExecID, progressSpec, cio.LogFile(os.DevNull)) + progress, err := task.Exec(ctx, taskExecID, progressSpec, ioc) if err != nil { return nil, fmt.Errorf("exec command: %w", err) } diff --git a/client/runtime_linux.go b/client/runtime_linux.go index ac84e69..d993808 100644 --- a/client/runtime_linux.go +++ b/client/runtime_linux.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/containerd/oci" "github.com/google/uuid" "github.com/opencontainers/runtime-spec/specs-go" + "github.com/samber/lo" "k8s.io/apimachinery/pkg/util/wait" "github.com/everoute/container/model" @@ -45,7 +46,7 @@ func (r *runtime) doPlatformConfig(ctx context.Context) error { func (r *runtime) setDefaultRuncPath(ctx context.Context) { // NOTE: prioritize to use containerd runc path /usr/bin/runc const containerdRuncPath = "/usr/bin/runc" - err := r.execHostCommand(ctx, "check_runc_path_"+uuid.New().String(), "test", "-f", containerdRuncPath) + err := r.execHostCommand(ctx, nil, "check_runc_path_"+uuid.New().String(), "test", "-f", containerdRuncPath) if err == nil { r.runcPath = containerdRuncPath } @@ -53,7 +54,7 @@ func (r *runtime) setDefaultRuncPath(ctx context.Context) { // In some version of OS, containers may not be destroyed correctly, if fs.may_detach_mounts is not set. func (r *runtime) enableMayDetachMounts(ctx context.Context) error { - return r.execHostCommand(ctx, "enable_fs_may_detach_mounts_"+uuid.New().String(), "sysctl", "-e", "-w", "fs.may_detach_mounts=1") + return r.execHostCommand(ctx, nil, "enable_fs_may_detach_mounts_"+uuid.New().String(), "sysctl", "-e", "-w", "fs.may_detach_mounts=1") } func (r *runtime) newTask(ctx context.Context, container containerd.Container, creator cio.Creator) (containerd.Task, error) { @@ -75,13 +76,13 @@ func (r *runtime) newTask(ctx context.Context, container containerd.Container, c killCommand := fmt.Sprintf("kill -9 $(ps --no-headers -o pid,cmd -p $(pidof containerd-shim-runc-v1 containerd-shim-runc-v2) | awk %s)", shellescape.Quote(fmt.Sprintf(`{if ($4 == "%s" && $6 == "%s") print $1}`, r.namespace, container.ID())), ) - _ = r.execHostCommand(ctx, "remove-task-shim"+uuid.New().String(), "sh", "-c", killCommand) + _ = r.execHostCommand(ctx, nil, "remove-task-shim"+uuid.New().String(), "sh", "-c", killCommand) // delete orphans runc container in namespace - _ = r.execHostCommand(ctx, "remove-runc-container"+uuid.New().String(), "runc", "--root="+filepath.Join("/run/containerd/runc/", r.namespace), "delete", "-f", container.ID()) + _ = r.execHostCommand(ctx, nil, "remove-runc-container"+uuid.New().String(), "runc", "--root="+filepath.Join("/run/containerd/runc/", r.namespace), "delete", "-f", container.ID()) // delete orphans containerd task in namespace - _ = r.execHostCommand(ctx, "remove-task-path"+uuid.New().String(), "rm", "-rf", filepath.Join("/run/containerd/io.containerd.runtime.v2.task/", r.namespace, container.ID())) + _ = r.execHostCommand(ctx, nil, "remove-task-path"+uuid.New().String(), "rm", "-rf", filepath.Join("/run/containerd/io.containerd.runtime.v2.task/", r.namespace, container.ID())) // to prevent indefinitely waiting, set default timeout to 1min. If ctx // has an earlier deadline, the timeout will be overridden @@ -96,8 +97,9 @@ func (r *runtime) newTask(ctx context.Context, container containerd.Container, c return task, err } -func (r *runtime) execHostCommand(ctx context.Context, name string, commands ...string) error { +func (r *runtime) execHostCommand(ctx context.Context, ioc cio.Creator, name string, commands ...string) error { ctx = namespaces.WithNamespace(ctx, r.namespace) + ioc = lo.If(ioc != nil, ioc).Else(cio.NullIO) specOpts := append( containerSpecOpts(r.namespace, nil, &model.Container{Name: name}), @@ -128,7 +130,7 @@ func (r *runtime) execHostCommand(ctx context.Context, name string, commands ... } defer nc.Delete(ctx) - task, err := nc.NewTask(ctx, cio.NullIO) + task, err := nc.NewTask(ctx, ioc) if err != nil { return fmt.Errorf("create task: %w", err) } diff --git a/logging/logrotate.go b/logging/logrotate.go index 21fd4ca..9a1e140 100644 --- a/logging/logrotate.go +++ b/logging/logrotate.go @@ -97,12 +97,12 @@ func (l *logrotate) SetupLogging(ctx context.Context) error { ) containerName := "setup-logging-" + uuid.New().String() - return l.runtime.NodeExecute(ctx, containerName, commands...) + return l.runtime.NodeExecute(ctx, nil, containerName, commands...) } func (l *logrotate) RemoveLogging(ctx context.Context) error { containerName := "remove-logging-" + uuid.New().String() - return l.runtime.NodeExecute(ctx, containerName, "rm", "-f", filepath.Join(l.dropInConfigDir, l.runtime.Namespace())) + return l.runtime.NodeExecute(ctx, nil, containerName, "rm", "-f", filepath.Join(l.dropInConfigDir, l.runtime.Namespace())) } //go:embed logrotate diff --git a/plugin/executor.go b/plugin/executor.go index 65ef853..cd3fc80 100644 --- a/plugin/executor.go +++ b/plugin/executor.go @@ -688,7 +688,7 @@ func (w *executor) doContainerExecHook(ctx context.Context, name, hookName strin func() { ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() - result, err := w.runtime.ExecCommand(ctx, name, hook.ExecCommand) + result, err := w.runtime.ExecCommand(ctx, nil, name, hook.ExecCommand) herr = client.HandleTaskResult(result, err) }() if herr == nil { @@ -768,7 +768,7 @@ func (w *executor) doCheck(ctx context.Context, containerName string, probe *mod if len(probe.ExecCommand) != 0 { // do check with exec command in container - result, err := w.runtime.ExecCommand(ctx, containerName, probe.ExecCommand) + result, err := w.runtime.ExecCommand(ctx, nil, containerName, probe.ExecCommand) err = client.HandleTaskResult(result, err) if err != nil { return fmt.Errorf("exec command %v: %s", probe.ExecCommand, err)