mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
feat: "exec" command to start processes inside remote containers (#139)
This commit is contained in:
@@ -28,6 +28,7 @@ type ContainerClient interface {
|
||||
RemoveContainer(ctx context.Context, serviceNameOrID, containerNameOrID string, opts container.RemoveOptions) error
|
||||
StartContainer(ctx context.Context, serviceNameOrID, containerNameOrID string) error
|
||||
StopContainer(ctx context.Context, serviceNameOrID, containerNameOrID string, opts container.StopOptions) error
|
||||
ExecContainer(ctx context.Context, serviceNameOrID, containerNameOrID string, config ExecOptions) (int, error)
|
||||
}
|
||||
|
||||
type DNSClient interface {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package api
|
||||
|
||||
import "io"
|
||||
|
||||
// ExecOptions contains configuration for executing a command in a container.
|
||||
type ExecOptions struct {
|
||||
// Command is the command to run in the container.
|
||||
Command []string
|
||||
// AttachStdin attaches the stdin stream to the exec session.
|
||||
AttachStdin bool
|
||||
// AttachStdout attaches the stdout stream to the exec session.
|
||||
AttachStdout bool
|
||||
// AttachStderr attaches the stderr stream to the exec session.
|
||||
AttachStderr bool
|
||||
// Tty allocates a pseudo-TTY for the exec session.
|
||||
Tty bool
|
||||
// Detach runs the command in the background without attaching to streams.
|
||||
Detach bool
|
||||
|
||||
//// Not yet implemented fields
|
||||
// User specifies the user to run the command as.
|
||||
User string
|
||||
// Privileged runs the command in privileged mode.
|
||||
Privileged bool
|
||||
// WorkingDir sets the working directory for the command.
|
||||
WorkingDir string
|
||||
// Env sets environment variables for the command.
|
||||
Env []string
|
||||
|
||||
// Client-side only fields (not serialized, not sent to server)
|
||||
// Stdin is the input stream. Defaults to os.Stdin if nil.
|
||||
Stdin io.Reader `json:"-"`
|
||||
// Stdout is the output stream. Defaults to os.Stdout if nil.
|
||||
Stdout io.Writer `json:"-"`
|
||||
// Stderr is the error stream. Defaults to os.Stderr if nil.
|
||||
Stderr io.Writer `json:"-"`
|
||||
}
|
||||
@@ -299,3 +299,49 @@ func (cli *Client) RemoveContainer(
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExecContainer executes a command in a container within the service.
|
||||
// If containerNameOrID is empty, the first container in the service will be used.
|
||||
func (cli *Client) ExecContainer(
|
||||
ctx context.Context, serviceNameOrID, containerNameOrID string, execOpts api.ExecOptions,
|
||||
) (int, error) {
|
||||
var ctr api.MachineServiceContainer
|
||||
|
||||
if containerNameOrID == "" {
|
||||
// Find the first (random) container in the service
|
||||
service, err := cli.InspectService(ctx, serviceNameOrID)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("inspect service: %w", err)
|
||||
}
|
||||
if len(service.Containers) == 0 {
|
||||
return -1, fmt.Errorf("no containers found in service %s", serviceNameOrID)
|
||||
}
|
||||
ctr = service.Containers[0]
|
||||
} else {
|
||||
// Find the specific container
|
||||
var err error
|
||||
ctr, err = cli.InspectContainer(ctx, serviceNameOrID, containerNameOrID)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("inspect container: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
machine, err := cli.InspectMachine(ctx, ctr.MachineID)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("inspect machine '%s': %w", ctr.MachineID, err)
|
||||
}
|
||||
|
||||
// Proxy Docker gRPC requests to the machine hosting the container
|
||||
ctx = proxyToMachine(ctx, machine.Machine)
|
||||
|
||||
// Execute the command in the container
|
||||
exitCode, err := cli.Docker.ExecContainer(ctx, machinedocker.ExecConfig{
|
||||
ContainerID: ctr.Container.ID,
|
||||
Options: execOpts,
|
||||
})
|
||||
if err != nil {
|
||||
return exitCode, fmt.Errorf("exec in container %s: %w", ctr.Container.Name, err)
|
||||
}
|
||||
|
||||
return exitCode, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user