...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/cmd/logs.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/chaosctl/cmd

     1  // Copyright 2020 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    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  // Run logs
    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  		// TODO: just use kubernetes native label selector
    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