mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Merge pull request #825 from brendandburns/runin
Add support for "run in"
This commit is contained in:
commit
adc57da3f3
@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
@ -63,6 +64,30 @@ func NewDockerPuller(client DockerInterface) DockerPuller {
|
||||
}
|
||||
}
|
||||
|
||||
type dockerContainerCommandRunner struct{}
|
||||
|
||||
func (d *dockerContainerCommandRunner) getRunInContainerCommand(containerID string, cmd []string) (*exec.Cmd, error) {
|
||||
args := append([]string{"exec"}, cmd...)
|
||||
command := exec.Command("/usr/sbin/nsinit", args...)
|
||||
command.Dir = fmt.Sprintf("/var/lib/docker/execdriver/native/%s", containerID)
|
||||
return command, nil
|
||||
}
|
||||
|
||||
// RunInContainer uses nsinit to run the command inside the container identified by containerID
|
||||
func (d *dockerContainerCommandRunner) RunInContainer(containerID string, cmd []string) ([]byte, error) {
|
||||
c, err := d.getRunInContainerCommand(containerID, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.CombinedOutput()
|
||||
}
|
||||
|
||||
// NewDockerContainerCommandRunner creates a ContainerCommandRunner which uses nsinit to run a command
|
||||
// inside a container.
|
||||
func NewDockerContainerCommandRunner() ContainerCommandRunner {
|
||||
return &dockerContainerCommandRunner{}
|
||||
}
|
||||
|
||||
func (p dockerPuller) Pull(image string) error {
|
||||
image, tag := parseImageName(image)
|
||||
|
||||
|
@ -89,6 +89,10 @@ func NewIntegrationTestKubelet(hn string, dc DockerInterface) *Kubelet {
|
||||
}
|
||||
}
|
||||
|
||||
type ContainerCommandRunner interface {
|
||||
RunInContainer(containerID string, cmd []string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Kubelet is the main kubelet implementation.
|
||||
type Kubelet struct {
|
||||
hostname string
|
||||
@ -107,6 +111,8 @@ type Kubelet struct {
|
||||
dockerPuller DockerPuller
|
||||
// Optional, defaults to /logs/ from /var/log
|
||||
logServer http.Handler
|
||||
// Optional, defaults to simple Docker implementation
|
||||
runner ContainerCommandRunner
|
||||
}
|
||||
|
||||
// Run starts the kubelet reacting to config updates
|
||||
@ -666,3 +672,20 @@ func (kl *Kubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
|
||||
// TODO: whitelist logs we are willing to serve
|
||||
kl.logServer.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
// Run a command in a container, returns the combined stdout, stderr as an array of bytes
|
||||
func (kl *Kubelet) RunInContainer(pod *Pod, container string, cmd []string) ([]byte, error) {
|
||||
if kl.runner == nil {
|
||||
return nil, fmt.Errorf("no runner specified.")
|
||||
}
|
||||
podFullName := GetPodFullName(pod)
|
||||
dockerContainers, err := getKubeletDockerContainers(kl.dockerClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dockerContainer, found := dockerContainers.FindPodContainer(podFullName, container)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("container not found (%s)", container)
|
||||
}
|
||||
return kl.runner.RunInContainer(dockerContainer.ID, cmd)
|
||||
}
|
||||
|
@ -843,6 +843,86 @@ func TestGetContainerInfoOnNonExistContainer(t *testing.T) {
|
||||
mockCadvisor.AssertExpectations(t)
|
||||
}
|
||||
|
||||
type fakeContainerCommandRunner struct {
|
||||
Cmd []string
|
||||
ID string
|
||||
E error
|
||||
}
|
||||
|
||||
func (f *fakeContainerCommandRunner) RunInContainer(id string, cmd []string) ([]byte, error) {
|
||||
f.Cmd = cmd
|
||||
f.ID = id
|
||||
return []byte{}, f.E
|
||||
}
|
||||
|
||||
func TestRunInContainerNoSuchPod(t *testing.T) {
|
||||
fakeCommandRunner := fakeContainerCommandRunner{}
|
||||
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||
fakeDocker.containerList = []docker.APIContainers{}
|
||||
kubelet.runner = &fakeCommandRunner
|
||||
|
||||
podName := "podFoo"
|
||||
podNamespace := "etcd"
|
||||
containerName := "containerFoo"
|
||||
output, err := kubelet.RunInContainer(
|
||||
&Pod{Name: podName, Namespace: podNamespace},
|
||||
containerName,
|
||||
[]string{"ls"})
|
||||
if output != nil {
|
||||
t.Errorf("unexpected non-nil command: %v", output)
|
||||
}
|
||||
if err == nil {
|
||||
t.Error("unexpected non-error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunInContainer(t *testing.T) {
|
||||
fakeCommandRunner := fakeContainerCommandRunner{}
|
||||
kubelet, _, fakeDocker := makeTestKubelet(t)
|
||||
kubelet.runner = &fakeCommandRunner
|
||||
|
||||
containerID := "abc1234"
|
||||
podName := "podFoo"
|
||||
podNamespace := "etcd"
|
||||
containerName := "containerFoo"
|
||||
|
||||
fakeDocker.containerList = []docker.APIContainers{
|
||||
{
|
||||
ID: containerID,
|
||||
Names: []string{"/k8s--" + containerName + "--" + podName + "." + podNamespace + "--1234"},
|
||||
},
|
||||
}
|
||||
|
||||
cmd := []string{"ls"}
|
||||
_, err := kubelet.RunInContainer(
|
||||
&Pod{Name: podName, Namespace: podNamespace},
|
||||
containerName,
|
||||
cmd)
|
||||
if fakeCommandRunner.ID != containerID {
|
||||
t.Errorf("unexected ID: %s", fakeCommandRunner.ID)
|
||||
}
|
||||
if !reflect.DeepEqual(fakeCommandRunner.Cmd, cmd) {
|
||||
t.Errorf("unexpected commnd: %s", fakeCommandRunner.Cmd)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerContainerCommand(t *testing.T) {
|
||||
runner := dockerContainerCommandRunner{}
|
||||
containerID := "1234"
|
||||
command := []string{"ls"}
|
||||
cmd, _ := runner.getRunInContainerCommand(containerID, command)
|
||||
if cmd.Dir != "/var/lib/docker/execdriver/native/"+containerID {
|
||||
t.Errorf("unexpected command CWD: %s", cmd.Dir)
|
||||
}
|
||||
if !reflect.DeepEqual(cmd.Args, []string{"/usr/sbin/nsinit", "exec", "ls"}) {
|
||||
t.Errorf("unexpectd command args: %s", cmd.Args)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var parseImageNameTests = []struct {
|
||||
imageName string
|
||||
name string
|
||||
|
Loading…
Reference in New Issue
Block a user