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