github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/diagnose.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 6 "github.com/jenkins-x/jx/v2/pkg/table" 7 "github.com/jenkins-x/jx/v2/pkg/util/system" 8 "k8s.io/client-go/kubernetes" 9 10 "github.com/jenkins-x/jx/v2/pkg/cmd/templates" 11 12 "github.com/jenkins-x/jx/v2/pkg/cmd/helper" 13 "github.com/jenkins-x/jx/v2/pkg/cmd/opts" 14 "github.com/jenkins-x/jx/v2/pkg/cmd/version" 15 "github.com/jenkins-x/jx/v2/pkg/health" 16 17 "github.com/pkg/errors" 18 19 "github.com/jenkins-x/jx-logging/pkg/log" 20 "github.com/jenkins-x/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 }