github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/diagnose.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/olli-ai/jx/v2/pkg/table"
     7  	"github.com/olli-ai/jx/v2/pkg/util/system"
     8  	"k8s.io/client-go/kubernetes"
     9  
    10  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    11  
    12  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    13  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    14  	"github.com/olli-ai/jx/v2/pkg/cmd/version"
    15  	"github.com/olli-ai/jx/v2/pkg/health"
    16  
    17  	"github.com/pkg/errors"
    18  
    19  	"github.com/jenkins-x/jx-logging/pkg/log"
    20  	"github.com/olli-ai/jx/v2/pkg/util"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  func getValidArgs() []string {
    25  	return []string{"", "version", "status", "pvc", "pods", "ingresses", "secrets", "configmaps", "health"}
    26  }
    27  
    28  var jxDiagnoseExample = templates.Examples(fmt.Sprintf(`
    29  	# To print diagnostic information about pods in n1 namespace
    30  	jx diagnose pods -n n1
    31  	Supported arguments to diagnose are %v
    32  	
    33  	Deprecated usage:
    34  	# To print all information
    35  	jx diagnose
    36  	
    37  	#To print specific resource information 
    38  	jx diagnose --show=pods --show=version
    39  `, getValidArgs()))
    40  
    41  // DiagnoseOptions struct contains the diagnose flags
    42  type DiagnoseOptions struct {
    43  	*opts.CommonOptions
    44  	Namespace string
    45  	HelmTLS   bool
    46  	//Deprecated
    47  	Show   []string
    48  	Runner util.Commander
    49  }
    50  
    51  //NewCmdDiagnose creates the diagnose command
    52  func NewCmdDiagnose(commonOpts *opts.CommonOptions) *cobra.Command {
    53  	options := &DiagnoseOptions{
    54  		CommonOptions: commonOpts,
    55  	}
    56  	cmd := &cobra.Command{
    57  		Use:       "diagnose ARG",
    58  		Short:     "Print diagnostic information about the Jenkins X installation",
    59  		Example:   jxDiagnoseExample,
    60  		ValidArgs: getValidArgs(),
    61  		//Todo: This will be removed by cobra.ExactValidArgs(1) after --show flag is removed
    62  		Args: cobra.OnlyValidArgs,
    63  		Run: func(cmd *cobra.Command, args []string) {
    64  			path, err := util.JXBinLocation()
    65  			helper.CheckErr(err)
    66  			runner := &util.Command{
    67  				Name: fmt.Sprintf("%s/kubectl", path),
    68  			}
    69  			options.Runner = runner
    70  			options.Cmd = cmd
    71  			options.Args = args
    72  			err = options.Run()
    73  			helper.CheckErr(err)
    74  		},
    75  	}
    76  	cmd.Flags().StringVarP(&options.Namespace, "namespace", "n", "", "The namespace to display the kube resources from. If left out, defaults to the current namespace")
    77  	cmd.Flags().StringArrayVarP(&options.Show, "show", "", []string{"version", "status", "pvc", "pods", "ingresses", "secrets", "configmaps"}, "Determine what information to diagnose")
    78  	cmd.Flags().BoolVarP(&options.HelmTLS, "helm-tls", "", false, "Whether to use TLS with helm")
    79  	_ = cmd.Flags().MarkDeprecated("show", "use jx diagnose <object> instead. This will be removed on July 1, 2020")
    80  	return cmd
    81  }
    82  
    83  // Run implements the diagnose command
    84  func (o *DiagnoseOptions) Run() error {
    85  	// Get the namespace to run the diagnostics in, and output it
    86  	kubeClient, ns, err := o.KubeClientAndDevNamespace()
    87  	if err != nil {
    88  		return errors.Wrap(err, "failed to create kubeClient")
    89  	}
    90  
    91  	log.Logger().Infof("Running in namespace: %s", util.ColorInfo(ns))
    92  	_, table := o.GetPackageVersions(ns, o.HelmTLS)
    93  
    94  	// os version
    95  	osVersion, err := o.GetOsVersion()
    96  	if err != nil {
    97  		log.Logger().Warnf("Failed to get OS version: %s", err)
    98  	} else {
    99  		table.AddRow("Operating System", util.ColorInfo(osVersion))
   100  	}
   101  
   102  	switch len(o.Args) {
   103  	//ToDo: This wont be required after the deprecated --show flag is removed
   104  	case 0:
   105  		err = runDeprecatedShow(o, table, kubeClient, ns)
   106  		if err != nil {
   107  			return err
   108  		}
   109  	case 1:
   110  		if o.showInfo("version") {
   111  			err := version.NewCmdVersion(o.CommonOptions).Execute()
   112  			if err != nil {
   113  				return err
   114  			}
   115  			// Render system level information
   116  			table.Render()
   117  		}
   118  
   119  		if o.showInfo("status") {
   120  			err := NewCmdStatus(o.CommonOptions).Execute()
   121  			if err != nil {
   122  				return err
   123  			}
   124  		}
   125  
   126  		if o.showInfo("pvc") {
   127  			err := printStatus(o, "Kubernetes PVCs", "kubectl", "get", "pvc", "--namespace", ns)
   128  			if err != nil {
   129  				return err
   130  			}
   131  		}
   132  
   133  		if o.showInfo("pods") {
   134  			err := printStatus(o, "Kubernetes Pods", "kubectl", "get", "po", "--namespace", ns)
   135  			if err != nil {
   136  				return err
   137  			}
   138  		}
   139  
   140  		if o.showInfo("ingresses") {
   141  			err := printStatus(o, "Kubernetes Ingresses", "kubectl", "get", "ingress", "--namespace", ns)
   142  			if err != nil {
   143  				return err
   144  			}
   145  		}
   146  
   147  		if o.showInfo("secrets") {
   148  			err := printStatus(o, "Kubernetes Secrets", "kubectl", "get", "secrets", "--namespace", ns)
   149  			if err != nil {
   150  				return err
   151  			}
   152  		}
   153  
   154  		if o.showInfo("configmaps") {
   155  			err := printStatus(o, "Kubernetes Configmaps", "kubectl", "get", "configmaps", "--namespace", ns)
   156  			if err != nil {
   157  				return err
   158  			}
   159  		}
   160  
   161  		if o.showInfo("health") {
   162  			err = health.Kuberhealthy(kubeClient, ns)
   163  			if err != nil {
   164  				return err
   165  			}
   166  		}
   167  	//ToDo: This wont be required after the deprecated --show flag is removed
   168  	default:
   169  		return errors.New("Only one argument is allowed")
   170  	}
   171  
   172  	log.Logger().Info("\nPlease visit https://jenkins-x.io/faq/issues/ for any known issues.")
   173  	log.Logger().Info("\nFinished printing diagnostic information.")
   174  	return nil
   175  }
   176  
   177  // Run the specified command (jx status, kubectl get po, etc) and print its output
   178  func printStatus(o *DiagnoseOptions, header string, command string, options ...string) error {
   179  	o.Runner.SetArgs(options)
   180  	output, err := o.Runner.RunWithoutRetry()
   181  	if err != nil {
   182  		log.Logger().Errorf("Unable to get the %s", header)
   183  		return err
   184  	}
   185  	// Print the output of the command, and add a little header at the top for formatting / readability
   186  	log.Logger().Infof("\n%s:\n%s", header, util.ColorInfo(output))
   187  	return nil
   188  }
   189  
   190  // Deprecated
   191  func (o *DiagnoseOptions) showOption(e string) bool {
   192  	for _, a := range o.Show {
   193  		if a == e {
   194  			return true
   195  		}
   196  	}
   197  	return false
   198  }
   199  
   200  func (o *DiagnoseOptions) showInfo(e string) bool {
   201  	for _, a := range o.Args {
   202  		if a == e {
   203  			return true
   204  		}
   205  	}
   206  	return false
   207  }
   208  
   209  // GetOsVersion returns a human friendly string of the current OS
   210  // in the case of an error this still returns a valid string for the details that can be found.
   211  func (o *DiagnoseOptions) GetOsVersion() (string, error) {
   212  	return system.GetOsVersion()
   213  }
   214  
   215  //Deprecated
   216  func runDeprecatedShow(o *DiagnoseOptions, table table.Table, kubeClient kubernetes.Interface, ns string) error {
   217  	if o.showOption("version") {
   218  		versionCmd := version.NewCmdVersion(o.CommonOptions)
   219  		// Ugly hack to prevent --show flag from being passed to the version command
   220  		versionCmd.SetArgs([]string{})
   221  		err := versionCmd.Execute()
   222  		if err != nil {
   223  			return err
   224  		}
   225  		// Render system level information
   226  		table.Render()
   227  		return nil
   228  	}
   229  
   230  	if o.showOption("status") {
   231  		statusCmd := NewCmdStatus(o.CommonOptions)
   232  		// Ugly hack to prevent --show flag from being passed to the status command
   233  		statusCmd.SetArgs([]string{})
   234  		err := statusCmd.Execute()
   235  		if err != nil {
   236  			return err
   237  		}
   238  		return nil
   239  	}
   240  
   241  	if o.showOption("pvc") {
   242  		err := printStatus(o, "Kubernetes PVCs", "kubectl", "get", "pvc", "--namespace", ns)
   243  		if err != nil {
   244  			return err
   245  		}
   246  		return nil
   247  	}
   248  
   249  	if o.showOption("pods") {
   250  		err := printStatus(o, "Kubernetes Pods", "kubectl", "get", "po", "--namespace", ns)
   251  		if err != nil {
   252  			return err
   253  		}
   254  		return nil
   255  	}
   256  
   257  	if o.showOption("ingresses") {
   258  		err := printStatus(o, "Kubernetes Ingresses", "kubectl", "get", "ingress", "--namespace", ns)
   259  		if err != nil {
   260  			return err
   261  		}
   262  		return nil
   263  	}
   264  
   265  	if o.showOption("secrets") {
   266  		err := printStatus(o, "Kubernetes Secrets", "kubectl", "get", "secrets", "--namespace", ns)
   267  		if err != nil {
   268  			return err
   269  		}
   270  		return nil
   271  	}
   272  
   273  	if o.showOption("configmaps") {
   274  		err := printStatus(o, "Kubernetes Configmaps", "kubectl", "get", "configmaps", "--namespace", ns)
   275  		if err != nil {
   276  			return err
   277  		}
   278  		return nil
   279  	}
   280  
   281  	if o.showOption("health") {
   282  		err := health.Kuberhealthy(kubeClient, ns)
   283  		if err != nil {
   284  			return err
   285  		}
   286  		return nil
   287  	}
   288  
   289  	// Handle error if unsupported show option is passed
   290  	return errors.New(fmt.Sprintf("Unsupported show option: %v", o.Show))
   291  }