| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 | package dockerimport (	"bytes"	"context"	"io"	"strconv"	"github.com/0xJacky/Nginx-UI/settings"	"github.com/docker/docker/api/types/container"	"github.com/docker/docker/pkg/stdcopy"	"github.com/uozi-tech/cosy"	"github.com/uozi-tech/cosy/logger")// Exec executes a command in a specific container and returns the output.func Exec(ctx context.Context, command []string) (string, error) {	if !settings.NginxSettings.RunningInAnotherContainer() {		return "", ErrNginxNotRunningInAnotherContainer	}	cli, err := initClient()	if err != nil {		return "", cosy.WrapErrorWithParams(ErrClientNotInitialized, err.Error())	}	defer cli.Close()	execConfig := container.ExecOptions{		AttachStdout: true,		AttachStderr: true, // Also attach stderr to capture errors from the command		Cmd:          command,	}	// Create the exec instance	execCreateResp, err := cli.ContainerExecCreate(ctx, settings.NginxSettings.ContainerName, execConfig)	if err != nil {		return "", cosy.WrapErrorWithParams(ErrFailedToExec, err.Error())	}	execID := execCreateResp.ID	// Attach to the exec instance	hijackedResp, err := cli.ContainerExecAttach(ctx, execID, container.ExecAttachOptions{})	if err != nil {		return "", cosy.WrapErrorWithParams(ErrFailedToAttach, err.Error())	}	defer hijackedResp.Close()	// Read the output	var outBuf, errBuf bytes.Buffer	outputDone := make(chan error)	go func() {		// stdcopy.StdCopy demultiplexes the stream into two buffers		_, err = stdcopy.StdCopy(&outBuf, &errBuf, hijackedResp.Reader)		outputDone <- err	}()	select {	case err := <-outputDone:		if err != nil && err != io.EOF { // io.EOF is expected when the stream finishes			return "", cosy.WrapErrorWithParams(ErrReadOutput, err.Error())		}	case <-ctx.Done():		return "", cosy.WrapErrorWithParams(ErrReadOutput, ctx.Err().Error())	}	// Optionally inspect the exec process to check the exit code	execInspectResp, err := cli.ContainerExecInspect(ctx, execID)	logger.Debug("docker exec result", outBuf.String(), errBuf.String())	if err != nil {		return "", cosy.WrapErrorWithParams(ErrExitUnexpected, err.Error())	} else if execInspectResp.ExitCode != 0 {		// Command exited with a non-zero status code. Return stderr as part of the error.		return outBuf.String(), cosy.WrapErrorWithParams(ErrExitUnexpected, strconv.Itoa(execInspectResp.ExitCode), errBuf.String())	}	// Return stdout if successful	return outBuf.String(), nil}
 |