1
2
3
4
5
6
7
8
9
10
11
12
13
14 package cmd
15
16 import (
17 "context"
18 "fmt"
19 "strings"
20
21 "github.com/go-logr/logr"
22 "github.com/pkg/errors"
23
24 "github.com/spf13/cobra"
25 v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/client-go/kubernetes"
27
28 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
29 "github.com/chaos-mesh/chaos-mesh/controllers/config"
30 cm "github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/common"
31 "github.com/chaos-mesh/chaos-mesh/pkg/selector"
32 )
33
34 type logsOptions struct {
35 logger logr.Logger
36 tail int64
37 node string
38 }
39
40 func NewLogsCmd(logger logr.Logger) (*cobra.Command, error) {
41 o := &logsOptions{
42 logger: logger,
43 }
44
45 logsCmd := &cobra.Command{
46 Use: `logs [-t LINE]`,
47 Short: `Print logs of controller-manager, chaos-daemon and chaos-dashboard`,
48 Long: `Print logs of controller-manager, chaos-daemon and chaos-dashboard, to provide debug information.
49
50 Examples:
51 # Default print all log of all chaosmesh components
52 chaosctl logs
53
54 # Print 100 log lines for chaosmesh components in node NODENAME
55 chaosctl logs -t 100 -n NODENAME`,
56 RunE: func(cmd *cobra.Command, args []string) error {
57 return o.Run(args)
58 },
59 SilenceErrors: true,
60 SilenceUsage: true,
61 ValidArgsFunction: noCompletions,
62 }
63
64 logsCmd.Flags().Int64VarP(&o.tail, "tail", "t", -1, "Number of lines of recent log")
65 logsCmd.Flags().StringVarP(&o.node, "node", "n", "", "Number of lines of recent log")
66 err := logsCmd.RegisterFlagCompletionFunc("node", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
67 clientset, err := cm.InitClientSet()
68 if err != nil {
69 return nil, cobra.ShellCompDirectiveDefault
70 }
71 return listNodes(toComplete, clientset.KubeCli)
72 })
73 if err != nil {
74 return nil, err
75 }
76 return logsCmd, nil
77 }
78
79
80 func (o *logsOptions) Run(args []string) error {
81 ctx, cancel := context.WithCancel(context.Background())
82 defer cancel()
83 c, err := cm.InitClientSet()
84 if err != nil {
85 o.logger.V(4).Info("failed to initialize clientset", "err", err)
86 return err
87 }
88
89 componentsNeeded := []string{"controller-manager", "chaos-daemon", "chaos-dashboard"}
90 for _, name := range componentsNeeded {
91 selectorSpec := v1alpha1.SelectorSpec{
92 LabelSelectors: map[string]string{"app.kubernetes.io/component": name},
93 }
94 if o.node != "" {
95 selectorSpec.Nodes = []string{o.node}
96 }
97
98
99 components, err := selector.SelectPods(ctx, c.CtrlCli, nil, selectorSpec, config.ControllerCfg.ClusterScoped, config.ControllerCfg.TargetNamespace, config.ControllerCfg.EnableFilterNamespace)
100 if err != nil {
101 return errors.Wrapf(err, "failed to SelectPods for component %s", name)
102 }
103 o.logger.V(4).Info("select pods for component", "component", name, "pods", components)
104 for _, comp := range components {
105 cm.PrettyPrint(fmt.Sprintf("[%s]", comp.Name), 0, cm.Cyan)
106 comLog, err := cm.Log(comp, o.tail, c.KubeCli)
107 if err != nil {
108 cm.PrettyPrint(err.Error(), 1, cm.Red)
109 } else {
110 cm.PrettyPrint(comLog, 1, cm.NoColor)
111 }
112 }
113 }
114 return nil
115 }
116
117 func listNodes(toComplete string, c *kubernetes.Clientset) ([]string, cobra.ShellCompDirective) {
118 nodes, err := c.CoreV1().Nodes().List(v1.ListOptions{})
119 if err != nil {
120 return nil, cobra.ShellCompDirectiveDefault
121 }
122 var ret []string
123 for _, ns := range nodes.Items {
124 if strings.HasPrefix(ns.Name, toComplete) {
125 ret = append(ret, ns.Name)
126 }
127 }
128 return ret, cobra.ShellCompDirectiveNoFileComp
129 }
130