1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package cmd
17
18 import (
19 "context"
20 "fmt"
21
22 "github.com/go-logr/logr"
23 "github.com/pkg/errors"
24 "github.com/spf13/cobra"
25
26 "github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/common"
27 "github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/debug"
28 )
29
30 type DebugOptions struct {
31 namespace string
32 }
33
34 const (
35 networkChaos = "networkchaos"
36 stressChaos = "stresschaos"
37 ioChaos = "iochaos"
38 httpChaos = "httpchaos"
39 )
40
41 func NewDebugCommand(logger logr.Logger, debugs map[string]debug.Debug) (*cobra.Command, error) {
42 o := &DebugOptions{}
43
44 debugCmd := &cobra.Command{
45 Use: `debug (CHAOSTYPE) [-c CHAOSNAME] [-n NAMESPACE]`,
46 Short: `Print the debug information for certain chaos`,
47 Long: `Print the debug information for certain chaos.
48 Currently support networkchaos, stresschaos, iochaos and httpchaos.
49
50 Examples:
51 # Return debug information from all networkchaos in default namespace
52 chaosctl debug networkchaos
53
54 # Return debug information from certain networkchaos
55 chaosctl debug networkchaos CHAOSNAME -n NAMESPACE`,
56 ValidArgsFunction: noCompletions,
57 }
58
59 for chaosType, debug := range debugs {
60 debugCmd.AddCommand(debugResourceCommand(o, chaosType, debug))
61 }
62
63 debugCmd.PersistentFlags().StringVarP(&o.namespace, "namespace", "n", "default", "namespace to find chaos")
64 err := debugCmd.RegisterFlagCompletionFunc("namespace", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
65 client, cancel, err := common.CreateClient(context.TODO(), managerNamespace, managerSvc)
66 if err != nil {
67 logger.Error(err, "fail to create client")
68 return nil, cobra.ShellCompDirectiveNoFileComp
69 }
70 defer cancel()
71
72 completion, err := client.ListNamespace(context.TODO())
73 if err != nil {
74 logger.Error(err, "fail to complete resource")
75 return nil, cobra.ShellCompDirectiveNoFileComp
76 }
77
78 return completion, cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveNoSpace
79 })
80 return debugCmd, err
81 }
82
83 func debugResourceCommand(option *DebugOptions, chaosType string, debug debug.Debug) *cobra.Command {
84 return &cobra.Command{
85 Use: fmt.Sprintf(`%s (CHAOSNAME) [-n NAMESPACE]`, chaosType),
86 Short: fmt.Sprintf(`Print the debug information for certain %s`, chaosType),
87 Long: fmt.Sprintf(`Print the debug information for certain %s`, chaosType),
88 RunE: func(cmd *cobra.Command, args []string) error {
89 client, cancel, err := common.CreateClient(context.TODO(), managerNamespace, managerSvc)
90 if err != nil {
91 return err
92 }
93 defer cancel()
94 return option.Run(debug(client), args)
95 },
96 SilenceErrors: true,
97 SilenceUsage: true,
98 ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
99 if len(args) != 0 {
100 return []string{}, cobra.ShellCompDirectiveNoFileComp
101 }
102 client, cancel, err := common.CreateClient(context.TODO(), managerNamespace, managerSvc)
103 if err != nil {
104 common.PrettyPrint(errors.Wrap(err, "create client").Error(), 0, common.Red)
105 return nil, cobra.ShellCompDirectiveNoFileComp
106 }
107 defer cancel()
108 return option.List(debug(client))
109 },
110 }
111 }
112
113
114 func (o *DebugOptions) Run(debugger debug.Debugger, args []string) error {
115 if len(args) > 1 {
116 return errors.New("only one chaos could be specified")
117 }
118 ctx, cancel := context.WithCancel(context.Background())
119 defer cancel()
120
121 chaosName := ""
122 if len(args) == 1 {
123 chaosName = args[0]
124 }
125
126 var result []*common.ChaosResult
127 var err error
128
129 result, err = debugger.Collect(ctx, o.namespace, chaosName)
130 if err != nil {
131 return err
132 }
133
134 common.PrintResult(result)
135 return nil
136 }
137
138
139 func (o *DebugOptions) List(debugger debug.Debugger) ([]string, cobra.ShellCompDirective) {
140 ctx, cancel := context.WithCancel(context.Background())
141 defer cancel()
142
143 chaos, err := debugger.List(ctx, o.namespace)
144 if err != nil {
145 common.PrettyPrint(errors.Wrap(err, "list chaos").Error(), 0, common.Red)
146 return nil, cobra.ShellCompDirectiveNoFileComp
147 }
148
149 return chaos, cobra.ShellCompDirectiveNoFileComp
150 }
151