func (o *DiagnosticsOptions) Validate() error { available := availableDiagnostics() if common := available.Intersection(sets.NewString(o.RequestedDiagnostics...)); len(common) == 0 { o.Logger.Error("CED3012", log.EvalTemplate("CED3012", "None of the requested diagnostics are available:\n {{.requested}}\nPlease try from the following:\n {{.available}}", log.Hash{"requested": o.RequestedDiagnostics, "available": available.List()})) return fmt.Errorf("No requested diagnostics are available: requested=%s available=%s", strings.Join(o.RequestedDiagnostics, " "), strings.Join(available.List(), " ")) } else if len(common) < len(o.RequestedDiagnostics) { o.Logger.Error("CED3013", log.EvalTemplate("CED3013", ` Of the requested diagnostics: {{.requested}} only these are available: {{.common}} The list of all possible is: {{.available}} `, log.Hash{"requested": o.RequestedDiagnostics, "common": common.List(), "available": available.List()})) return fmt.Errorf("Not all requested diagnostics are available: missing=%s requested=%s available=%s", strings.Join(sets.NewString(o.RequestedDiagnostics...).Difference(available).List(), " "), strings.Join(o.RequestedDiagnostics, " "), strings.Join(available.List(), " ")) } return nil }
// determineRequestedDiagnostics determines which diagnostic the user wants to run // based on the -d list and the available diagnostics. // returns error or diagnostic names func determineRequestedDiagnostics(available []string, requested []string, logger *log.Logger) (error, []string) { diagnostics := []string{} if len(requested) == 0 { // not specified, use the available list diagnostics = available } else if diagnostics = sets.NewString(requested...).Intersection(sets.NewString(available...)).List(); len(diagnostics) == 0 { logger.Error("CED6001", log.EvalTemplate("CED6001", "None of the requested diagnostics are available:\n {{.requested}}\nPlease try from the following:\n {{.available}}", log.Hash{"requested": requested, "available": available})) return fmt.Errorf("No requested diagnostics available"), diagnostics } else if len(diagnostics) < len(requested) { logger.Error("CED6002", log.EvalTemplate("CED6002", "Of the requested diagnostics:\n {{.requested}}\nonly these are available:\n {{.diagnostics}}\nThe list of all possible is:\n {{.available}}", log.Hash{"requested": requested, "diagnostics": diagnostics, "available": available})) return fmt.Errorf("Not all requested diagnostics are available"), diagnostics } // else it's a valid list. return nil, diagnostics }
func (d *NodeDefinitions) Check() types.DiagnosticResult { r := types.NewDiagnosticResult("NodeDefinition") nodes, err := d.KubeClient.Core().Nodes().List(kapi.ListOptions{}) if err != nil { r.Error("DClu0001", err, fmt.Sprintf(clientErrorGettingNodes, err)) return r } anyNodesAvail := false for _, node := range nodes.Items { var ready *kapi.NodeCondition for i, condition := range node.Status.Conditions { switch condition.Type { // Each condition appears only once. Currently there's only one... used to be more case kapi.NodeReady: ready = &node.Status.Conditions[i] } } if ready == nil || ready.Status != kapi.ConditionTrue { templateData := log.Hash{"node": node.Name} if ready == nil { templateData["status"] = "None" templateData["reason"] = "There is no readiness record." } else { templateData["status"] = ready.Status templateData["reason"] = ready.Reason } r.Warn("DClu0002", nil, log.EvalTemplate("DClu0002", nodeNotReady, templateData)) } else if node.Spec.Unschedulable { r.Warn("DClu0003", nil, log.EvalTemplate("DClu0003", nodeNotSched, log.Hash{"node": node.Name})) } else { anyNodesAvail = true } } if !anyNodesAvail { r.Error("DClu0004", nil, "There were no nodes available to use. No new pods can be scheduled.") } return r }
// RunDiagnostics builds diagnostics based on the options and executes them, returning a summary. func (o DiagnosticsOptions) RunDiagnostics() (bool, error, int, int) { failed := false warnings := []error{} errors := []error{} diagnostics := []types.Diagnostic{} AvailableDiagnostics := util.NewStringSet() AvailableDiagnostics.Insert(availableClientDiagnostics.List()...) AvailableDiagnostics.Insert(availableClusterDiagnostics.List()...) AvailableDiagnostics.Insert(availableHostDiagnostics.List()...) if len(o.RequestedDiagnostics) == 0 { o.RequestedDiagnostics = AvailableDiagnostics.List() } else if common := intersection(util.NewStringSet(o.RequestedDiagnostics...), AvailableDiagnostics); len(common) == 0 { o.Logger.Error("CED3012", log.EvalTemplate("CED3012", "None of the requested diagnostics are available:\n {{.requested}}\nPlease try from the following:\n {{.available}}", log.Hash{"requested": o.RequestedDiagnostics, "available": AvailableDiagnostics.List()})) return false, fmt.Errorf("No requested diagnostics available"), 0, 1 } else if len(common) < len(o.RequestedDiagnostics) { errors = append(errors, fmt.Errorf("Not all requested diagnostics are available")) o.Logger.Error("CED3013", log.EvalTemplate("CED3013", ` Of the requested diagnostics: {{.requested}} only these are available: {{.common}} The list of all possible is: {{.available}} `, log.Hash{"requested": o.RequestedDiagnostics, "common": common.List(), "available": AvailableDiagnostics.List()})) } func() { // don't trust discovery/build of diagnostics; wrap panic nicely in case of developer error defer func() { if r := recover(); r != nil { failed = true errors = append(errors, fmt.Errorf("While building the diagnostics, a panic was encountered.\nThis is a bug in diagnostics. Stack trace follows : \n%v", r)) } }() detected, detectWarnings, detectErrors := o.detectClientConfig() // may log and return problems for _, warn := range detectWarnings { warnings = append(warnings, warn) } for _, err := range detectErrors { errors = append(errors, err) } if !detected { // there just plain isn't any client config file available o.Logger.Notice("CED3014", "No client configuration specified; skipping client and cluster diagnostics.") } else if rawConfig, err := o.buildRawConfig(); rawConfig == nil { // client config is totally broken - won't parse etc (problems may have been detected and logged) o.Logger.Error("CED3015", fmt.Sprintf("Client configuration failed to load; skipping client and cluster diagnostics due to error: %s", err.Error())) errors = append(errors, err) } else { if err != nil { // error encountered, proceed with caution o.Logger.Error("CED3016", fmt.Sprintf("Client configuration loading encountered an error, but proceeding anyway. Error was:\n%s", err.Error())) errors = append(errors, err) } clientDiags, ok, err := o.buildClientDiagnostics(rawConfig) failed = failed || !ok if ok { diagnostics = append(diagnostics, clientDiags...) } if err != nil { errors = append(errors, err) } clusterDiags, ok, err := o.buildClusterDiagnostics(rawConfig) failed = failed || !ok if ok { diagnostics = append(diagnostics, clusterDiags...) } if err != nil { errors = append(errors, err) } } hostDiags, ok, err := o.buildHostDiagnostics() failed = failed || !ok if ok { diagnostics = append(diagnostics, hostDiags...) } if err != nil { errors = append(errors, err) } }() if failed { return failed, kutilerrors.NewAggregate(errors), len(warnings), len(errors) } failed, err, numWarnings, numErrors := o.Run(diagnostics) numWarnings += len(warnings) numErrors += len(errors) return failed, err, numWarnings, numErrors }
// RunDiagnostics builds diagnostics based on the options and executes them, returning a summary. func (o DiagnosticsOptions) RunDiagnostics() (bool, error, int, int) { failed := false warnings := []error{} errors := []error{} diagnostics := []types.Diagnostic{} available := availableDiagnostics() if len(o.RequestedDiagnostics) == 0 { o.RequestedDiagnostics = available.List() } else if common := intersection(sets.NewString(o.RequestedDiagnostics...), available); len(common) == 0 { o.Logger.Error("CED3012", log.EvalTemplate("CED3012", "None of the requested diagnostics are available:\n {{.requested}}\nPlease try from the following:\n {{.available}}", log.Hash{"requested": o.RequestedDiagnostics, "available": available.List()})) return false, fmt.Errorf("No requested diagnostics available"), 0, 1 } else if len(common) < len(o.RequestedDiagnostics) { errors = append(errors, fmt.Errorf("Not all requested diagnostics are available")) o.Logger.Error("CED3013", log.EvalTemplate("CED3013", ` Of the requested diagnostics: {{.requested}} only these are available: {{.common}} The list of all possible is: {{.available}} `, log.Hash{"requested": o.RequestedDiagnostics, "common": common.List(), "available": available.List()})) } // If not given master/client config file locations, check if the defaults exist // and adjust the options accordingly: if len(o.MasterConfigLocation) == 0 { if _, err := os.Stat(StandardMasterConfigPath); !os.IsNotExist(err) { o.MasterConfigLocation = StandardMasterConfigPath } } if len(o.NodeConfigLocation) == 0 { if _, err := os.Stat(StandardNodeConfigPath); !os.IsNotExist(err) { o.NodeConfigLocation = StandardNodeConfigPath } } func() { // don't trust discovery/build of diagnostics; wrap panic nicely in case of developer error defer func() { if r := recover(); r != nil { failed = true stack := debug.Stack() errors = append(errors, fmt.Errorf("While building the diagnostics, a panic was encountered.\nThis is a bug in diagnostics. Error and stack trace follow: \n%v\n%s", r, stack)) } }() detected, detectWarnings, detectErrors := o.detectClientConfig() // may log and return problems for _, warn := range detectWarnings { warnings = append(warnings, warn) } for _, err := range detectErrors { errors = append(errors, err) } if !detected { // there just plain isn't any client config file available o.Logger.Notice("CED3014", "No client configuration specified; skipping client and cluster diagnostics.") } else if rawConfig, err := o.buildRawConfig(); err != nil { // client config is totally broken - won't parse etc (problems may have been detected and logged) o.Logger.Error("CED3015", fmt.Sprintf("Client configuration failed to load; skipping client and cluster diagnostics due to error: %s", err.Error())) errors = append(errors, err) } else { clientDiags, ok, err := o.buildClientDiagnostics(rawConfig) failed = failed || !ok if ok { diagnostics = append(diagnostics, clientDiags...) } if err != nil { errors = append(errors, err) } clusterDiags, ok, err := o.buildClusterDiagnostics(rawConfig) failed = failed || !ok if ok { diagnostics = append(diagnostics, clusterDiags...) } if err != nil { errors = append(errors, err) } } hostDiags, ok, err := o.buildHostDiagnostics() failed = failed || !ok if ok { diagnostics = append(diagnostics, hostDiags...) } if err != nil { errors = append(errors, err) } }() if failed { return failed, kutilerrors.NewAggregate(errors), len(warnings), len(errors) } failed, err, numWarnings, numErrors := o.Run(diagnostics) numWarnings += len(warnings) numErrors += len(errors) return failed, err, numWarnings, numErrors }