1
2
3
4
5
6
7
8
9
10
11
12
13
14 package common
15
16 import (
17 "bytes"
18 "context"
19 "fmt"
20 "io/ioutil"
21 "strings"
22
23 "github.com/pkg/errors"
24
25 "google.golang.org/grpc/grpclog"
26 v1 "k8s.io/api/core/v1"
27 "k8s.io/client-go/kubernetes"
28 "k8s.io/client-go/tools/remotecommand"
29 kubectlscheme "k8s.io/kubectl/pkg/scheme"
30 "sigs.k8s.io/controller-runtime/pkg/client/config"
31
32 "github.com/chaos-mesh/chaos-mesh/pkg/bpm"
33 )
34
35
36
37
38 func Exec(ctx context.Context, pod v1.Pod, cmd string, c *kubernetes.Clientset) (string, error) {
39 name := pod.GetObjectMeta().GetName()
40 namespace := pod.GetObjectMeta().GetNamespace()
41
42
43
44 containerName := pod.Spec.Containers[0].Name
45
46 req := c.CoreV1().RESTClient().Post().
47 Resource("pods").
48 Name(name).
49 Namespace(namespace).
50 SubResource("exec")
51
52 req.VersionedParams(&v1.PodExecOptions{
53 Container: containerName,
54 Command: []string{"/bin/sh", "-c", cmd},
55 Stdin: false,
56 Stdout: true,
57 Stderr: true,
58 TTY: false,
59 }, kubectlscheme.ParameterCodec)
60
61 var stdout, stderr bytes.Buffer
62 exec, err := remotecommand.NewSPDYExecutor(config.GetConfigOrDie(), "POST", req.URL())
63 if err != nil {
64 return "", errors.Wrapf(err, "error in creating NewSPDYExecutor for pod %s/%s", pod.GetNamespace(), pod.GetName())
65 }
66 err = exec.Stream(remotecommand.StreamOptions{
67 Stdin: nil,
68 Stdout: &stdout,
69 Stderr: &stderr,
70 })
71 if err != nil {
72 if stderr.String() != "" {
73 return "", fmt.Errorf("error: %s\npod: %s\ncommand: %s", strings.TrimSuffix(stderr.String(), "\n"), pod.Name, cmd)
74 }
75 return "", errors.Wrapf(err, "error in streaming remotecommand: pod: %s/%s, command: %s", pod.GetNamespace(), pod.Name, cmd)
76 }
77 if stderr.String() != "" {
78 return "", fmt.Errorf("error of command %s: %s", cmd, stderr.String())
79 }
80 return stdout.String(), nil
81 }
82
83
84 func ExecBypass(ctx context.Context, pod v1.Pod, daemon v1.Pod, cmd string, c *kubernetes.Clientset) (string, error) {
85
86
87 grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
88 pid, err := GetPidFromPod(ctx, pod, daemon)
89 if err != nil {
90 return "", err
91 }
92
93 cmdBuilder := bpm.DefaultProcessBuilder(cmd).SetNS(pid, bpm.MountNS).SetNS(pid, bpm.PidNS).SetContext(ctx)
94 return Exec(ctx, daemon, cmdBuilder.Build().Cmd.String(), c)
95 }
96