1
16
17 package pod
18
19 import (
20 "bytes"
21 "context"
22 "io"
23 "net/url"
24 "strings"
25
26 v1 "k8s.io/api/core/v1"
27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28 "k8s.io/client-go/kubernetes/scheme"
29 restclient "k8s.io/client-go/rest"
30 "k8s.io/client-go/tools/remotecommand"
31 "k8s.io/kubernetes/test/e2e/framework"
32
33 "github.com/onsi/gomega"
34 )
35
36
37 type ExecOptions struct {
38 Command []string
39 Namespace string
40 PodName string
41 ContainerName string
42 Stdin io.Reader
43 CaptureStdout bool
44 CaptureStderr bool
45
46 PreserveWhitespace bool
47 Quiet bool
48 }
49
50
51
52
53 func ExecWithOptions(f *framework.Framework, options ExecOptions) (string, string, error) {
54 if !options.Quiet {
55 framework.Logf("ExecWithOptions %+v", options)
56 }
57 config, err := framework.LoadConfig()
58 framework.ExpectNoError(err, "failed to load restclient config")
59
60 const tty = false
61
62 framework.Logf("ExecWithOptions: Clientset creation")
63 req := f.ClientSet.CoreV1().RESTClient().Post().
64 Resource("pods").
65 Name(options.PodName).
66 Namespace(options.Namespace).
67 SubResource("exec").
68 Param("container", options.ContainerName)
69 req.VersionedParams(&v1.PodExecOptions{
70 Container: options.ContainerName,
71 Command: options.Command,
72 Stdin: options.Stdin != nil,
73 Stdout: options.CaptureStdout,
74 Stderr: options.CaptureStderr,
75 TTY: tty,
76 }, scheme.ParameterCodec)
77
78 var stdout, stderr bytes.Buffer
79 framework.Logf("ExecWithOptions: execute(POST %s)", req.URL())
80 err = execute("POST", req.URL(), config, options.Stdin, &stdout, &stderr, tty)
81 if options.PreserveWhitespace {
82 return stdout.String(), stderr.String(), err
83 }
84 return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err
85 }
86
87
88
89 func ExecCommandInContainerWithFullOutput(f *framework.Framework, podName, containerName string, cmd ...string) (string, string, error) {
90
91 return ExecWithOptions(f, ExecOptions{
92 Command: cmd,
93 Namespace: f.Namespace.Name,
94 PodName: podName,
95 ContainerName: containerName,
96 Stdin: nil,
97 CaptureStdout: true,
98 CaptureStderr: true,
99 PreserveWhitespace: false,
100 })
101 }
102
103
104 func ExecCommandInContainer(f *framework.Framework, podName, containerName string, cmd ...string) string {
105 stdout, stderr, err := ExecCommandInContainerWithFullOutput(f, podName, containerName, cmd...)
106 framework.Logf("Exec stderr: %q", stderr)
107 framework.ExpectNoError(err,
108 "failed to execute command in pod %v, container %v: %v",
109 podName, containerName, err)
110 return stdout
111 }
112
113
114 func ExecShellInContainer(f *framework.Framework, podName, containerName string, cmd string) string {
115 return ExecCommandInContainer(f, podName, containerName, "/bin/sh", "-c", cmd)
116 }
117
118 func execCommandInPod(ctx context.Context, f *framework.Framework, podName string, cmd ...string) string {
119 pod, err := NewPodClient(f).Get(ctx, podName, metav1.GetOptions{})
120 framework.ExpectNoError(err, "failed to get pod %v", podName)
121 gomega.Expect(pod.Spec.Containers).NotTo(gomega.BeEmpty())
122 return ExecCommandInContainer(f, podName, pod.Spec.Containers[0].Name, cmd...)
123 }
124
125 func execCommandInPodWithFullOutput(ctx context.Context, f *framework.Framework, podName string, cmd ...string) (string, string, error) {
126 pod, err := NewPodClient(f).Get(ctx, podName, metav1.GetOptions{})
127 framework.ExpectNoError(err, "failed to get pod %v", podName)
128 gomega.Expect(pod.Spec.Containers).NotTo(gomega.BeEmpty())
129 return ExecCommandInContainerWithFullOutput(f, podName, pod.Spec.Containers[0].Name, cmd...)
130 }
131
132
133 func ExecShellInPod(ctx context.Context, f *framework.Framework, podName string, cmd string) string {
134 return execCommandInPod(ctx, f, podName, "/bin/sh", "-c", cmd)
135 }
136
137
138 func ExecShellInPodWithFullOutput(ctx context.Context, f *framework.Framework, podName string, cmd string) (string, string, error) {
139 return execCommandInPodWithFullOutput(ctx, f, podName, "/bin/sh", "-c", cmd)
140 }
141
142 func execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error {
143 exec, err := remotecommand.NewSPDYExecutor(config, method, url)
144 if err != nil {
145 return err
146 }
147 return exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{
148 Stdin: stdin,
149 Stdout: stdout,
150 Stderr: stderr,
151 Tty: tty,
152 })
153 }
154
View as plain text