From 319fffff917a73082b24474fbb19bf7465d9e7db Mon Sep 17 00:00:00 2001 From: Marcin Dobrochowski Date: Sat, 29 Nov 2025 21:42:41 +0100 Subject: [PATCH 1/4] add filtering istio messages by level --- internal/cmd/alpha/diagnose/istio.go | 24 +++++++++++++ internal/cmdcommon/types/format.go | 4 +-- internal/cmdcommon/types/istiolevel.go | 48 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 internal/cmdcommon/types/istiolevel.go diff --git a/internal/cmd/alpha/diagnose/istio.go b/internal/cmd/alpha/diagnose/istio.go index 6ca8c2d0b..10c25cdbb 100644 --- a/internal/cmd/alpha/diagnose/istio.go +++ b/internal/cmd/alpha/diagnose/istio.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "os" + "regexp" + "strings" "time" "github.com/kyma-project/cli.v3/internal/clierror" @@ -14,6 +16,7 @@ import ( "github.com/kyma-project/cli.v3/internal/out" "github.com/spf13/cobra" istioformatting "istio.io/istio/istioctl/pkg/util/formatting" + istioanalysisdiag "istio.io/istio/pkg/config/analysis/diag" istioresource "istio.io/istio/pkg/config/resource" istiolog "istio.io/istio/pkg/log" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,6 +31,7 @@ type diagnoseIstioConfig struct { namespace string allNamespaces bool outputFormat types.Format + outputLevel types.IstioLevel outputPath string verbose bool timeout time.Duration @@ -49,6 +53,9 @@ func NewDiagnoseIstioCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command { # Analyze Istio configuration in a specific namespace kyma alpha diagnose istio --namespace my-namespace + # Print only warnings and errors + kyma alpha diagnose istio --level warning + # Output as JSON to a file kyma alpha diagnose istio --format json --output istio-diagnostics.json`, @@ -66,6 +73,7 @@ func NewDiagnoseIstioCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command { cmd.Flags().BoolVarP(&cfg.allNamespaces, "all-namespaces", "A", false, "Analyzes all namespaces") cmd.Flags().StringVarP(&cfg.namespace, "namespace", "n", "", "The namespace that the workload instances belongs to") cmd.Flags().VarP(&cfg.outputFormat, "format", "f", "Output format (possible values: json, yaml)") + cmd.Flags().VarP(&cfg.outputLevel, "level", "l", "Output message level (possible values: info, warning, error)") cmd.Flags().StringVarP(&cfg.outputPath, "output", "o", "", "Path to the diagnostic output file. If not provided the output is printed to stdout") cmd.Flags().BoolVar(&cfg.verbose, "verbose", false, "Displays verbose output, including error details during diagnostics collection") cmd.Flags().DurationVar(&cfg.timeout, "timeout", 30*time.Second, "Timeout for diagnosis") @@ -95,6 +103,8 @@ func diagnoseIstio(cfg *diagnoseIstioConfig) clierror.Error { return err } + diagnosticData.Messages = filterDataByLevel(diagnosticData.Messages, cfg.outputLevel.ToInternalIstioLevel()) + err = printIstioOutput(diagnosticData, cfg.outputFormat, cfg.outputPath) if err != nil { return err @@ -102,6 +112,16 @@ func diagnoseIstio(cfg *diagnoseIstioConfig) clierror.Error { return nil } +func filterDataByLevel(messages istioanalysisdiag.Messages, minLevel istioanalysisdiag.Level) istioanalysisdiag.Messages { + var filtered []istioanalysisdiag.Message + for _, msg := range messages { + if msg.Type.Level().IsWorseThanOrEqualTo(minLevel) { + filtered = append(filtered, msg) + } + } + return filtered +} + func calculateNamespace(allNamespaces bool, namespace string) string { if allNamespaces { return metav1.NamespaceAll @@ -190,6 +210,10 @@ func printIstioOutput(analysisResult *istioanalysislocal.AnalysisResult, format if err != nil { return clierror.Wrap(err, clierror.New("failed to format output")) } + re := regexp.MustCompile(`(?m)^\t+`) + output = re.ReplaceAllStringFunc(output, func(match string) string { + return strings.Repeat(" ", len(match)) + }) printer.Msgfln(output) return nil } diff --git a/internal/cmdcommon/types/format.go b/internal/cmdcommon/types/format.go index 945477b18..1191acef3 100644 --- a/internal/cmdcommon/types/format.go +++ b/internal/cmdcommon/types/format.go @@ -38,13 +38,13 @@ func (f *Format) String() string { func (f *Format) Set(v string) error { for _, format := range availableFormats { - if *f == format { + if v == format.String() { *f = Format(v) return nil } } - return errors.New(fmt.Sprintf("invalid output format '%s'", *f)) + return errors.New(fmt.Sprintf("invalid output format '%s'", v)) } func (f *Format) Type() string { diff --git a/internal/cmdcommon/types/istiolevel.go b/internal/cmdcommon/types/istiolevel.go new file mode 100644 index 000000000..0167b5e3f --- /dev/null +++ b/internal/cmdcommon/types/istiolevel.go @@ -0,0 +1,48 @@ +package types + +import ( + "fmt" + "strings" + + "github.com/pkg/errors" + istioanalysisdiag "istio.io/istio/pkg/config/analysis/diag" +) + +const ( + InfoIstioLevel IstioLevel = "info" + WarningIstioLevel IstioLevel = "warning" + ErrorIstioLevel IstioLevel = "error" +) + +var ( + availableIstioLevels = []IstioLevel{ + InfoIstioLevel, + WarningIstioLevel, + ErrorIstioLevel, + } +) + +type IstioLevel string + +func (f *IstioLevel) String() string { + return string(*f) +} + +func (f *IstioLevel) Set(v string) error { + for _, format := range availableIstioLevels { + if v == format.String() { + *f = IstioLevel(v) + return nil + } + } + + return errors.New(fmt.Sprintf("invalid istio level '%s'", v)) +} + +func (f *IstioLevel) Type() string { + return "string" +} + +func (f *IstioLevel) ToInternalIstioLevel() istioanalysisdiag.Level { + return istioanalysisdiag.GetUppercaseStringToLevelMap()[strings.ToUpper(f.String())] +} From b3255737d851e33ed3f65e7f06f444459b2f01b2 Mon Sep 17 00:00:00 2001 From: Marcin Dobrochowski Date: Sat, 29 Nov 2025 21:49:32 +0100 Subject: [PATCH 2/4] regenerate docs --- docs/user/gen-docs/kyma_alpha_diagnose_istio.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user/gen-docs/kyma_alpha_diagnose_istio.md b/docs/user/gen-docs/kyma_alpha_diagnose_istio.md index 62c96873f..d841df88c 100644 --- a/docs/user/gen-docs/kyma_alpha_diagnose_istio.md +++ b/docs/user/gen-docs/kyma_alpha_diagnose_istio.md @@ -21,6 +21,9 @@ kyma alpha diagnose istio [flags] # Analyze Istio configuration in a specific namespace kyma alpha diagnose istio --namespace my-namespace + # Print only warnings and errors + kyma alpha diagnose istio --level warning + # Output as JSON to a file kyma alpha diagnose istio --format json --output istio-diagnostics.json ``` @@ -30,6 +33,7 @@ kyma alpha diagnose istio [flags] ```text -A, --all-namespaces Analyzes all namespaces -f, --format string Output format (possible values: json, yaml) + -l, --level string Output message level (possible values: info, warning, error) -n, --namespace string The namespace that the workload instances belongs to -o, --output string Path to the diagnostic output file. If not provided the output is printed to stdout --timeout duration Timeout for diagnosis (default "30s") From b3fab2de21a5f6bc8c8ddf16ad6b55885bb5b09e Mon Sep 17 00:00:00 2001 From: Marcin Dobrochowski Date: Tue, 2 Dec 2025 15:56:45 +0100 Subject: [PATCH 3/4] remove shorthand for level; fix level defaulting --- internal/cmd/alpha/diagnose/istio.go | 2 +- internal/cmdcommon/types/istiolevel.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/cmd/alpha/diagnose/istio.go b/internal/cmd/alpha/diagnose/istio.go index 10c25cdbb..2fbdae998 100644 --- a/internal/cmd/alpha/diagnose/istio.go +++ b/internal/cmd/alpha/diagnose/istio.go @@ -73,7 +73,7 @@ func NewDiagnoseIstioCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command { cmd.Flags().BoolVarP(&cfg.allNamespaces, "all-namespaces", "A", false, "Analyzes all namespaces") cmd.Flags().StringVarP(&cfg.namespace, "namespace", "n", "", "The namespace that the workload instances belongs to") cmd.Flags().VarP(&cfg.outputFormat, "format", "f", "Output format (possible values: json, yaml)") - cmd.Flags().VarP(&cfg.outputLevel, "level", "l", "Output message level (possible values: info, warning, error)") + cmd.Flags().Var(&cfg.outputLevel, "level", "Output message level (possible values: info, warning, error)") cmd.Flags().StringVarP(&cfg.outputPath, "output", "o", "", "Path to the diagnostic output file. If not provided the output is printed to stdout") cmd.Flags().BoolVar(&cfg.verbose, "verbose", false, "Displays verbose output, including error details during diagnostics collection") cmd.Flags().DurationVar(&cfg.timeout, "timeout", 30*time.Second, "Timeout for diagnosis") diff --git a/internal/cmdcommon/types/istiolevel.go b/internal/cmdcommon/types/istiolevel.go index 0167b5e3f..ba1bad250 100644 --- a/internal/cmdcommon/types/istiolevel.go +++ b/internal/cmdcommon/types/istiolevel.go @@ -44,5 +44,9 @@ func (f *IstioLevel) Type() string { } func (f *IstioLevel) ToInternalIstioLevel() istioanalysisdiag.Level { - return istioanalysisdiag.GetUppercaseStringToLevelMap()[strings.ToUpper(f.String())] + levelName := f.String() + if levelName == "" { + return istioanalysisdiag.Info + } + return istioanalysisdiag.GetUppercaseStringToLevelMap()[strings.ToUpper(levelName)] } From 74c75fea2599fac9c4c9ef56127710a6e4805508 Mon Sep 17 00:00:00 2001 From: Marcin Dobrochowski Date: Tue, 2 Dec 2025 15:59:38 +0100 Subject: [PATCH 4/4] regenerate docs --- docs/user/gen-docs/kyma_alpha_diagnose_istio.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/gen-docs/kyma_alpha_diagnose_istio.md b/docs/user/gen-docs/kyma_alpha_diagnose_istio.md index d841df88c..eef00cfbb 100644 --- a/docs/user/gen-docs/kyma_alpha_diagnose_istio.md +++ b/docs/user/gen-docs/kyma_alpha_diagnose_istio.md @@ -33,7 +33,7 @@ kyma alpha diagnose istio [flags] ```text -A, --all-namespaces Analyzes all namespaces -f, --format string Output format (possible values: json, yaml) - -l, --level string Output message level (possible values: info, warning, error) + --level string Output message level (possible values: info, warning, error) -n, --namespace string The namespace that the workload instances belongs to -o, --output string Path to the diagnostic output file. If not provided the output is printed to stdout --timeout duration Timeout for diagnosis (default "30s")