1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package server
17
18 import (
19 "bytes"
20 "context"
21 "io"
22 "strings"
23
24 "github.com/pkg/errors"
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.StreamWithContext(ctx, remotecommand.StreamOptions{
67 Stdin: nil,
68 Stdout: &stdout,
69 Stderr: &stderr,
70 })
71 if err != nil {
72 if stderr.String() != "" {
73 return "", errors.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 "", errors.Errorf("error of command %s: %s", cmd, stderr.String())
79 }
80 return stdout.String(), nil
81 }
82
83
84 func (r *Resolver) ExecBypass(ctx context.Context, pod *v1.Pod, cmd string, nsTypes ...bpm.NsType) (string, error) {
85
86
87 grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, io.Discard))
88 pid, err := r.GetPidFromPod(ctx, pod)
89 if err != nil {
90 return "", err
91 }
92
93 podResolver := &podResolver{Resolver: r}
94 daemon, err := podResolver.Daemon(ctx, pod)
95 if err != nil {
96 return "", err
97 }
98
99 cmdBuilder := bpm.DefaultProcessBuilder(cmd)
100 for _, nsType := range nsTypes {
101 cmdBuilder = cmdBuilder.SetNS(pid, nsType)
102 }
103
104 return exec(
105 ctx, daemon,
106 cmdBuilder.EnableLocalMnt().SetContext(ctx).Build(ctx).Cmd.String(),
107 r.Clientset,
108 )
109 }
110