1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package debug
17
18 import (
19 "context"
20 "fmt"
21 "strings"
22
23 "github.com/hasura/go-graphql-client"
24
25 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
26 "github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/common"
27 ctrlclient "github.com/chaos-mesh/chaos-mesh/pkg/ctrl/client"
28 )
29
30 type ioDebugger struct {
31 client *ctrlclient.CtrlClient
32 }
33
34 func IODebug(client *ctrlclient.CtrlClient) Debugger {
35 return &ioDebugger{
36 client: client,
37 }
38 }
39
40 func (d *ioDebugger) Collect(ctx context.Context, namespace, chaosName string) ([]*common.ChaosResult, error) {
41 var results []*common.ChaosResult
42
43 var name *graphql.String
44 if chaosName != "" {
45 n := graphql.String(chaosName)
46 name = &n
47 }
48
49 var query struct {
50 Namespace []struct {
51 IOChaos []struct {
52 Name string
53 Podios []struct {
54 Namespace string
55 Name string
56
57 Spec struct {
58 VolumeMountPath string
59 Container *string
60 Actions []struct {
61 Type v1alpha1.IOChaosType
62 v1alpha1.Filter `json:",inline"`
63 Faults []v1alpha1.IoFault
64 Latency string
65 Ino *uint64 `json:"ino,omitempty"`
66 Size *uint64 `json:"size,omitempty"`
67 Blocks *uint64 `json:"blocks,omitempty"`
68 Atime *v1alpha1.Timespec `json:"atime,omitempty"`
69 Mtime *v1alpha1.Timespec `json:"mtime,omitempty"`
70 Ctime *v1alpha1.Timespec `json:"ctime,omitempty"`
71 Kind *v1alpha1.FileType `json:"kind,omitempty"`
72 Perm *uint `json:"perm,omitempty"`
73 Nlink *uint `json:"nlink,omitempty"`
74 UID *uint `json:"uid,omitempty"`
75 GID *uint `json:"gid,omitempty"`
76 Rdev *uint `json:"rdev,omitempty"`
77 Filling *v1alpha1.FillingType `json:"filling,omitempty"`
78 MaxOccurrences *int64 `json:"maxOccurrences,omitempty"`
79 MaxLength *int64 `json:"maxLength,omitempty"`
80 }
81 }
82 Pod struct {
83 Mounts []string
84 Processes []struct {
85 Pid string
86 Command string
87 Fds []struct {
88 Fd, Target string
89 }
90 }
91 }
92 }
93 } `graphql:"iochaos(name: $name)"`
94 } `graphql:"namespace(ns: $namespace)"`
95 }
96
97 variables := map[string]interface{}{
98 "namespace": graphql.String(namespace),
99 "name": name,
100 }
101
102 err := d.client.QueryClient.Query(ctx, &query, variables)
103 if err != nil {
104 return nil, err
105 }
106
107 if len(query.Namespace) == 0 {
108 return results, nil
109 }
110
111 for _, ioChaos := range query.Namespace[0].IOChaos {
112 result := &common.ChaosResult{
113 Name: ioChaos.Name,
114 }
115
116 for _, podiochaos := range ioChaos.Podios {
117 podResult := common.PodResult{
118 Name: podiochaos.Name,
119 }
120
121 podResult.Items = append(podResult.Items, common.ItemResult{Name: "Mount Information", Value: strings.Join(podiochaos.Pod.Mounts, "\n")})
122 for _, process := range podiochaos.Pod.Processes {
123 var fds []string
124 for _, fd := range process.Fds {
125 fds = append(fds, fmt.Sprintf("%s -> %s", fd.Fd, fd.Target))
126 }
127 podResult.Items = append(podResult.Items, common.ItemResult{
128 Name: fmt.Sprintf("file descriptors of PID: %s, COMMAND: %s", process.Pid, process.Command),
129 Value: strings.Join(fds, "\n"),
130 })
131 }
132 output, err := common.MarshalChaos(podiochaos.Spec)
133 if err != nil {
134 return nil, err
135 }
136 podResult.Items = append(podResult.Items, common.ItemResult{Name: "podiochaos", Value: output})
137 result.Pods = append(result.Pods, podResult)
138 }
139
140 results = append(results, result)
141 }
142 return results, nil
143 }
144
145 func (d *ioDebugger) List(ctx context.Context, namespace string) ([]string, error) {
146 var query struct {
147 Namespace []struct {
148 IOChaos []struct {
149 Name string
150 } `graphql:"iochaos"`
151 } `graphql:"namespace(ns: $namespace)"`
152 }
153
154 variables := map[string]interface{}{
155 "namespace": graphql.String(namespace),
156 }
157
158 err := d.client.QueryClient.Query(ctx, &query, variables)
159 if err != nil {
160 return nil, err
161 }
162
163 if len(query.Namespace) == 0 {
164 return nil, nil
165 }
166
167 var names []string
168 for _, ioChaos := range query.Namespace[0].IOChaos {
169 names = append(names, string(ioChaos.Name))
170 }
171 return names, nil
172 }
173