Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package stern for openSUSE:Factory checked 
in at 2025-01-27 20:57:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/stern (Old)
 and      /work/SRC/openSUSE:Factory/.stern.new.2316 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "stern"

Mon Jan 27 20:57:37 2025 rev:12 rq:1240588 version:1.32.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/stern/stern.changes      2024-10-11 
17:03:49.106461445 +0200
+++ /work/SRC/openSUSE:Factory/.stern.new.2316/stern.changes    2025-01-27 
20:58:59.067858924 +0100
@@ -1,0 +2,13 @@
+Tue Jan 21 06:10:13 UTC 2025 - opensuse_buildserv...@ojkastl.de
+
+- Update to version 1.32.0:
+  * Update CHANGELOG for v1.32.0 (#334)
+  * Fix a typo `toUTC` (#333)
+  * Update dependencies for Kubernetes 1.32 (#332)
+  * Add `--condition` (#276)
+  * Add check for when `--no-follow` is set with `--tail=0` (#331)
+  * Implement JSON pretty print (#324)
+  * Fix descriptions of `extjson` and `ppextjson` (#325)
+  * Allow `levelColor` template function to parse numbers (#321)
+
+-------------------------------------------------------------------

Old:
----
  stern-1.31.0.obscpio

New:
----
  stern-1.32.0.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ stern.spec ++++++
--- /var/tmp/diff_new_pack.90MIeQ/_old  2025-01-27 20:59:00.135902946 +0100
+++ /var/tmp/diff_new_pack.90MIeQ/_new  2025-01-27 20:59:00.135902946 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package stern
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,24 +16,28 @@
 #
 
 
-%define __arch_install_post export NO_BRP_STRIP_DEBUG=true
-
 Name:           stern
-Version:        1.31.0
+Version:        1.32.0
 Release:        0
 Summary:        Multi pod and container log tailing for Kubernetes
 License:        Apache-2.0
 URL:            https://github.com/stern/stern
 Source:         stern-%{version}.tar.gz
 Source1:        vendor.tar.gz
-BuildRequires:  go >= 1.22
+BuildRequires:  go >= 1.23.5
 
 %description
-Stern allows you to tail multiple pods on Kubernetes and multiple containers 
within the pod. Each result is color coded for quicker debugging.
-
-The query is a regular expression so the pod name can easily be filtered and 
you don't need to specify the exact id (for instance omitting the deployment 
id). If a pod is deleted it gets removed from tail and if a new pod is added it 
automatically gets tailed.
+Stern allows you to tail multiple pods on Kubernetes and multiple containers
+within the pod. Each result is color coded for quicker debugging.
 
-When a pod contains multiple containers Stern can tail all of them too without 
having to do this manually for each one. Simply specify the container flag to 
limit what containers to show. By default all containers are listened to.
+The query is a regular expression so the pod name can easily be filtered and
+you don't need to specify the exact id (for instance omitting the deployment
+id). If a pod is deleted it gets removed from tail and if a new pod is added it
+automatically gets tailed.
+
+When a pod contains multiple containers Stern can tail all of them too without
+having to do this manually for each one. Simply specify the container flag to
+limit what containers to show. By default all containers are listened to.
 
 %prep
 %autosetup -p 1 -a 1

++++++ _service ++++++
--- /var/tmp/diff_new_pack.90MIeQ/_old  2025-01-27 20:59:00.163904101 +0100
+++ /var/tmp/diff_new_pack.90MIeQ/_new  2025-01-27 20:59:00.167904265 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/stern/stern</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.31.0</param>
+    <param name="revision">v1.32.0</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.90MIeQ/_old  2025-01-27 20:59:00.187905090 +0100
+++ /var/tmp/diff_new_pack.90MIeQ/_new  2025-01-27 20:59:00.187905090 +0100
@@ -3,6 +3,6 @@
                 <param name="url">https://github.com/wercker/stern</param>
               <param 
name="changesrevision">94f4ffb3b98a9dcd34aedf00f8a7e95b623b25d3</param></service><service
 name="tar_scm">
                 <param name="url">https://github.com/stern/stern</param>
-              <param 
name="changesrevision">ae7a33d6fbe59f08be9252f45b94b64fc6ab0281</param></service></servicedata>
+              <param 
name="changesrevision">5e06930fe21f951f079880ec2c13cd688aa5ca09</param></service></servicedata>
 (No newline at EOF)
 

++++++ stern-1.31.0.obscpio -> stern-1.32.0.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/.github/workflows/release.yaml 
new/stern-1.32.0/.github/workflows/release.yaml
--- old/stern-1.31.0/.github/workflows/release.yaml     2024-10-07 
11:23:01.000000000 +0200
+++ new/stern-1.32.0/.github/workflows/release.yaml     2025-01-21 
02:14:50.000000000 +0100
@@ -23,6 +23,6 @@
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     - name: Update new version in krew-index
-      uses: rajatjindal/krew-release-bot@v0.0.46
+      uses: rajatjindal/krew-release-bot@v0.0.47
       with:
         krew_template_file: dist/krew/stern.yaml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/CHANGELOG.md 
new/stern-1.32.0/CHANGELOG.md
--- old/stern-1.31.0/CHANGELOG.md       2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/CHANGELOG.md       2025-01-21 02:14:50.000000000 +0100
@@ -1,3 +1,39 @@
+# v1.32.0
+
+## :zap: Notable Changes
+
+### A new template function `prettyJSON`
+
+You can now use a new template function `prettyJSON` that parse input and emit 
it as pretty printed JSON. If it parse fails output string as is.
+
+```
+# Will try to parse .Message as JSON and pretty print it, if not json will 
output as is
+stern --template='{{ .Message | prettyJSON }}{{"\n"}}' backend
+# Or with parsed json, will drop non-json logs because of `with`
+stern --template='{{ with $msg := .Message | tryParseJSON }}{{ prettyJSON $msg 
}}{{"\n"}}{{end}}' backend
+```
+
+### A new template function `bunyanLevelColor`
+
+You can now use a new template function `bunyanLevelColor` that print 
[bunyan](https://github.com/trentm/node-bunyan) numeric log level using 
appropriate color.
+
+### A new flag `--condition`
+
+A new `--condition` allows you to filter logs with the pod condition on: 
`[condition-name[=condition-value]`. The default condition-value is true. Match 
is case-insensitive. Currently, it is only supported with --tail=0 or 
--no-follow.
+
+```
+# Only display logs for pods that are not ready:
+stern . --condition=ready=false --tail=0
+```
+
+## Changes
+
+* Add `--condition` (#276) 2576972 (Felipe Santos)
+* Add check for when `--no-follow` is set with `--tail=0` (#331) 276e906 
(Felipe Santos)
+* Implement JSON pretty print (#324) ccd8add (Fabio Napoleoni)
+* Fix descriptions of `extjson` and `ppextjson` (#325) d9a9858 (Takashi Kusumi)
+* Allow `levelColor` template function to parse numbers (#321) db69276 (Jimmie 
Högklint)
+
 # v1.31.0
 
 ## Changes
@@ -65,7 +101,7 @@
 The following template functions now support UNIX time seconds with 
nanoseconds (e.g., `1136171056.02`).
 
 - `toRFC3339Nano`
-- `toTUC`
+- `toUTC`
 - `toTimestamp`
 
 ## Changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/Dockerfile new/stern-1.32.0/Dockerfile
--- old/stern-1.31.0/Dockerfile 2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/Dockerfile 2025-01-21 02:14:50.000000000 +0100
@@ -1,4 +1,4 @@
-FROM gcr.io/distroless/static-debian10
+FROM gcr.io/distroless/static-debian12
 LABEL org.opencontainers.image.source https://github.com/stern/stern
 COPY stern /usr/local/bin/
 ENTRYPOINT ["/usr/local/bin/stern"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/Makefile new/stern-1.32.0/Makefile
--- old/stern-1.31.0/Makefile   2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/Makefile   2025-01-21 02:14:50.000000000 +0100
@@ -5,9 +5,9 @@
        go build -o dist/stern .
 
 TOOLS_BIN_DIR := $(CURDIR)/hack/tools/bin
-GORELEASER_VERSION ?= v2.3.2
+GORELEASER_VERSION ?= v2.5.1
 GORELEASER := $(TOOLS_BIN_DIR)/goreleaser
-GOLANGCI_LINT_VERSION ?= v1.61.0
+GOLANGCI_LINT_VERSION ?= v1.63.4
 GOLANGCI_LINT := $(TOOLS_BIN_DIR)/golangci-lint
 VALIDATE_KREW_MAIFEST_VERSION ?= v0.4.4
 VALIDATE_KREW_MAIFEST := $(TOOLS_BIN_DIR)/validate-krew-manifest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/README.md new/stern-1.32.0/README.md
--- old/stern-1.31.0/README.md  2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/README.md  2025-01-21 02:14:50.000000000 +0100
@@ -74,6 +74,7 @@
  `--all-namespaces`, `-A`    | `false`                       | If present, 
tail across all namespaces. A specific namespace is ignored even if specified 
with --namespace.
  `--color`                   | `auto`                        | Force set color 
output. 'auto':  colorize if tty attached, 'always': always colorize, 'never': 
never colorize.
  `--completion`              |                               | Output stern 
command-line completion code for the specified shell. Can be 'bash', 'zsh' or 
'fish'.
+ `--condition`               |                               | The condition 
to filter on: [condition-name[=condition-value]. The default condition-value is 
true. Match is case-insensitive. Currently only supported with --tail=0 or 
--no-follow.
  `--config`                  | `~/.config/stern/config.yaml` | Path to the 
stern config file
  `--container`, `-c`         | `.*`                          | Container name 
when multiple containers in pod. (regular expression)
  `--container-colors`        |                               | Specifies the 
colors used to highlight container names. Use the same format as --pod-colors. 
Defaults to the values of --pod-colors if omitted, and must match its length.
@@ -118,7 +119,7 @@
 
 ### config file
 
-You can use the config file to change the default values of stern options. The 
default config file path is `~/.config/stern/config.yaml`. 
+You can use the config file to change the default values of stern options. The 
default config file path is `~/.config/stern/config.yaml`.
 
 ```yaml
 # <flag name>: <value>
@@ -134,11 +135,13 @@
 stern supports outputting custom log messages.  There are a few predefined
 templates which you can use by specifying the `--output` flag:
 
-| output    | description                                                      
                                     |
-|-----------|-------------------------------------------------------------------------------------------------------|
-| `default` | Displays the namespace, pod and container, and decorates it with 
color depending on --color           |
-| `raw`     | Only outputs the log message itself, useful when your logs are 
json and you want to pipe them to `jq` |
-| `json`    | Marshals the log struct to json. Useful for programmatic 
purposes                                     |
+| output      | description                                                    
                                       |
+|-------------|-------------------------------------------------------------------------------------------------------|
+| `default`   | Displays the namespace, pod and container, and decorates it 
with color depending on --color           |
+| `raw`       | Only outputs the log message itself, useful when your logs are 
json and you want to pipe them to `jq` |
+| `json`      | Marshals the log struct to json. Useful for programmatic 
purposes                                     |
+| `extjson`   | Outputs extended JSON with colorized pod/container names       
                                       |
+| `ppextjson` | Pretty-prints extended JSON with colorized pod/container names 
                                       |
 
 It accepts a custom template through the `--template` flag, which will be
 compiled to a Go template and then used for every log message. This Go template
@@ -155,28 +158,27 @@
 The following functions are available within the template (besides the [builtin
 functions](https://golang.org/pkg/text/template/#hdr-Functions)):
 
-| func            | arguments             | description                        
                                               |
-|-----------------|-----------------------|-----------------------------------------------------------------------------------|
-| `json`          | `object`              | Marshal the object and output it 
as a json text                                   |
-| `color`         | `color.Color, string` | Wrap the text in color 
(.ContainerColor and .PodColor provided)                   |
-| `parseJSON`     | `string`              | Parse string as JSON               
                                               |
-| `tryParseJSON`  | `string`              | Attempt to parse string as JSON, 
return nil on failure                             |
-| `extractJSONParts`    | `string, ...string` | Parse string as JSON and 
concatenate the given keys.                          |
-| `tryExtractJSONParts` | `string, ...string` | Attempt to parse string as 
JSON and concatenate the given keys. , return text on failure |
-| `extjson`       | `string`              | Parse the object as json and 
output colorized json                                |
-| `ppextjson`     | `string`              | Parse the object as json and 
output pretty-print colorized json                   |
-| `toRFC3339Nano` | `object`              | Parse timestamp (string, int, 
json.Number) and output it using RFC3339Nano format |
-| `toTimestamp`   | `object, string [, string]` | Parse timestamp (string, 
int, json.Number) and output it using the given layout in the timezone that is 
optionally given (defaults to UTC). |
-| `levelColor`    | `string`              | Print log level using appropriate 
color                                           |
-| `colorBlack`    | `string`              | Print text using black color       
                                               |
-| `colorRed`      | `string`              | Print text using red color         
                                               |
-| `colorGreen`    | `string`              | Print text using green color       
                                               |
-| `colorYellow`   | `string`              | Print text using yellow color      
                                               |
-| `colorBlue`     | `string`              | Print text using blue color        
                                               |
-| `colorMagenta`  | `string`              | Print text using magenta color     
                                               |
-| `colorCyan`     | `string`              | Print text using cyan color        
                                               |
-| `colorWhite`    | `string`              | Print text using white color       
                                               |
-
+| func                  | arguments                   | description            
                                                                                
                                     |
+|-----------------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
+| `json`                | `object`                    | Marshal the object and 
output it as a json text                                                        
                                     |
+| `color`               | `color.Color, string`       | Wrap the text in color 
(.ContainerColor and .PodColor provided)                                        
                                     |
+| `parseJSON`           | `string`                    | Parse string as JSON   
                                                                                
                                     |
+| `tryParseJSON`        | `string`                    | Attempt to parse 
string as JSON, return nil on failure                                           
                                           |
+| `extractJSONParts`    | `string, ...string`         | Parse string as JSON 
and concatenate the given keys.                                                 
                                       |
+| `tryExtractJSONParts` | `string, ...string`         | Attempt to parse 
string as JSON and concatenate the given keys. , return text on failure         
                                           |
+| `prettyJSON`          | `any`                       | Parse input and emit 
it as pretty printed JSON, if parse fails output string as is.                  
                                       |
+| `toRFC3339Nano`       | `object`                    | Parse timestamp 
(string, int, json.Number) and output it using RFC3339Nano format               
                                            |
+| `toTimestamp`         | `object, string [, string]` | Parse timestamp 
(string, int, json.Number) and output it using the given layout in the timezone 
that is optionally given (defaults to UTC). |
+| `levelColor`          | `string`                    | Print log level using 
appropriate color                                                               
                                      |
+| `bunyanLevelColor`    | `string`                    | Print 
[bunyan](https://github.com/trentm/node-bunyan) numeric log level using 
appropriate color                                             |
+| `colorBlack`          | `string`                    | Print text using black 
color                                                                           
                                     |
+| `colorRed`            | `string`                    | Print text using red 
color                                                                           
                                       |
+| `colorGreen`          | `string`                    | Print text using green 
color                                                                           
                                     |
+| `colorYellow`         | `string`                    | Print text using 
yellow color                                                                    
                                           |
+| `colorBlue`           | `string`                    | Print text using blue 
color                                                                           
                                      |
+| `colorMagenta`        | `string`                    | Print text using 
magenta color                                                                   
                                           |
+| `colorCyan`           | `string`                    | Print text using cyan 
color                                                                           
                                      |
+| `colorWhite`          | `string`                    | Print text using white 
color                                                                           
                                     |
 
 ### Log level verbosity
 
@@ -326,6 +328,15 @@
 stern --template='{{.PodName}}/{{.ContainerName}} {{ with $msg := .Message | 
tryParseJSON }}[{{ colorGreen (toRFC3339Nano $msg.ts) }}] {{ levelColor 
$msg.level }} ({{ colorCyan $msg.caller }}) {{ $msg.msg }}{{ else }} {{ 
.Message }} {{ end }}{{"\n"}}' backend
 ```
 
+Pretty print JSON (if it is JSON) and output it:
+
+```
+# Will try to parse .Message as JSON and pretty print it, if not json will 
output as is
+stern --template='{{ .Message | prettyJSON }}{{"\n"}}' backend
+# Or with parsed json, will drop non-json logs because of `with`
+stern --template='{{ with $msg := .Message | tryParseJSON }}{{ prettyJSON $msg 
}}{{"\n"}}{{end}}' backend
+```
+
 Load custom template from file:
 
 ```
@@ -350,6 +361,12 @@
 stern --stdin < service.log
 ```
 
+Only display logs for pods that are not ready:
+
+```
+stern . --condition=ready=false --tail=0
+```
+
 ## Completion
 
 Stern supports command-line auto completion for bash, zsh or fish. `stern
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/cmd/cmd.go new/stern-1.32.0/cmd/cmd.go
--- old/stern-1.31.0/cmd/cmd.go 2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/cmd/cmd.go 2025-01-21 02:14:50.000000000 +0100
@@ -60,6 +60,7 @@
        timezone            string
        since               time.Duration
        namespaces          []string
+       condition           string
        exclude             []string
        include             []string
        highlight           []string
@@ -106,6 +107,7 @@
                color:               "auto",
                container:           ".*",
                containerStates:     []string{stern.ALL_STATES},
+               condition:           "",
                initContainers:      true,
                ephemeralContainers: true,
                output:              "default",
@@ -161,7 +163,13 @@
                return errors.New("One of pod-query, --selector, 
--field-selector, --prompt or --stdin is required")
        }
        if o.selector != "" && o.resource != "" {
-               return errors.New("--selector and the <resource>/<name> query 
can not be set at the same time")
+               return errors.New("--selector and the <resource>/<name> query 
cannot be set at the same time")
+       }
+       if o.noFollow && o.tail == 0 {
+               return errors.New("--no-follow cannot be used with --tail=0")
+       }
+       if o.condition != "" && o.tail != 0 && !o.noFollow {
+               return errors.New("--condition is currently only supported with 
--tail=0 or --no-follow")
        }
 
        return nil
@@ -225,6 +233,14 @@
                return nil, errors.Wrap(err, "failed to compile regular 
expression for highlight filter")
        }
 
+       condition := stern.Condition{}
+       if o.condition != "" {
+               condition, err = stern.NewCondition(o.condition)
+               if err != nil {
+                       return nil, err
+               }
+       }
+
        containerStates := []stern.ContainerState{}
        for _, containerStateStr := range makeUnique(o.containerStates) {
                containerState, err := 
stern.NewContainerState(containerStateStr)
@@ -304,6 +320,7 @@
                Location:              location,
                ContainerQuery:        container,
                ExcludeContainerQuery: excludeContainer,
+               Condition:             condition,
                ContainerStates:       containerStates,
                Exclude:               exclude,
                Include:               include,
@@ -422,6 +439,7 @@
        fs.StringArrayVarP(&o.exclude, "exclude", "e", o.exclude, "Log lines to 
exclude. (regular expression)")
        fs.StringArrayVarP(&o.excludeContainer, "exclude-container", "E", 
o.excludeContainer, "Container name to exclude when multiple containers in pod. 
(regular expression)")
        fs.StringArrayVar(&o.excludePod, "exclude-pod", o.excludePod, "Pod name 
to exclude. (regular expression)")
+       fs.StringVar(&o.condition, "condition", o.condition, "The condition to 
filter on: [condition-name[=condition-value]. The default condition-value is 
true. Match is case-insensitive. Currently only supported with --tail=0 or 
--no-follow.")
        fs.BoolVar(&o.noFollow, "no-follow", o.noFollow, "Exit when all logs 
have been shown.")
        fs.StringArrayVarP(&o.include, "include", "i", o.include, "Log lines to 
include. (regular expression)")
        fs.StringArrayVarP(&o.highlight, "highlight", "H", o.highlight, "Log 
lines to highlight. (regular expression)")
@@ -575,6 +593,27 @@
                        }
                        return strings.TrimSuffix(string(b), "\n"), nil
                },
+               "prettyJSON": func(value any) string {
+                       var data map[string]any
+
+                       switch v := value.(type) {
+                       case string:
+                               if err := json.Unmarshal([]byte(v), &data); err 
!= nil {
+                                       return v
+                               }
+                       case map[string]any:
+                               data = v
+                       default:
+                               return fmt.Sprintf("%v", value)
+                       }
+
+                       b, err := json.MarshalIndent(data, "", "  ")
+                       if err != nil {
+                               return fmt.Sprintf("%v", value)
+                       }
+
+                       return string(b)
+               },
                "toRFC3339Nano": func(ts any) string {
                        return toTime(ts).Format(time.RFC3339Nano)
                },
@@ -610,31 +649,71 @@
                "colorMagenta": color.MagentaString,
                "colorCyan":    color.CyanString,
                "colorWhite":   color.WhiteString,
-               "levelColor": func(level string) string {
+               "levelColor": func(value any) string {
+                       switch level := value.(type) {
+                       case string:
+                               var levelColor *color.Color
+                               switch strings.ToLower(level) {
+                               case "debug":
+                                       levelColor = color.New(color.FgMagenta)
+                               case "info":
+                                       levelColor = color.New(color.FgBlue)
+                               case "warn":
+                                       levelColor = color.New(color.FgYellow)
+                               case "warning":
+                                       levelColor = color.New(color.FgYellow)
+                               case "error":
+                                       levelColor = color.New(color.FgRed)
+                               case "dpanic":
+                                       levelColor = color.New(color.FgRed)
+                               case "panic":
+                                       levelColor = color.New(color.FgRed)
+                               case "fatal":
+                                       levelColor = color.New(color.FgCyan)
+                               case "critical":
+                                       levelColor = color.New(color.FgCyan)
+                               default:
+                                       return level
+                               }
+                               return levelColor.SprintFunc()(level)
+                       default:
+                               return ""
+                       }
+               },
+               "bunyanLevelColor": func(value any) string {
+                       var lv int64
+                       var err error
+
+                       switch level := value.(type) {
+                       // tryParseJSON yields json.Number
+                       case json.Number:
+                               lv, err = level.Int64()
+                               if err != nil {
+                                       return ""
+                               }
+                       // parseJSON yields float64
+                       case float64:
+                               lv = int64(level)
+                       default:
+                               return ""
+                       }
+
                        var levelColor *color.Color
-                       switch strings.ToLower(level) {
-                       case "debug":
+                       switch {
+                       case lv < 30:
                                levelColor = color.New(color.FgMagenta)
-                       case "info":
+                       case lv < 40:
                                levelColor = color.New(color.FgBlue)
-                       case "warn":
-                               levelColor = color.New(color.FgYellow)
-                       case "warning":
+                       case lv < 50:
                                levelColor = color.New(color.FgYellow)
-                       case "error":
+                       case lv < 60:
                                levelColor = color.New(color.FgRed)
-                       case "dpanic":
-                               levelColor = color.New(color.FgRed)
-                       case "panic":
-                               levelColor = color.New(color.FgRed)
-                       case "fatal":
-                               levelColor = color.New(color.FgCyan)
-                       case "critical":
+                       case lv < 100:
                                levelColor = color.New(color.FgCyan)
                        default:
-                               return level
+                               return strconv.FormatInt(lv, 10)
                        }
-                       return levelColor.SprintFunc()(level)
+                       return levelColor.SprintFunc()(lv)
                },
        }
        template, err := template.New("log").Funcs(funs).Parse(t)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/cmd/cmd_test.go 
new/stern-1.32.0/cmd/cmd_test.go
--- old/stern-1.31.0/cmd/cmd_test.go    2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/cmd/cmd_test.go    2025-01-21 02:14:50.000000000 +0100
@@ -120,7 +120,41 @@
 
                                return o
                        }(),
-                       "--selector and the <resource>/<name> query can not be 
set at the same time",
+                       "--selector and the <resource>/<name> query cannot be 
set at the same time",
+               },
+               {
+                       "Specify both --no-follow and --tail=0",
+                       func() *options {
+                               o := NewOptions(streams)
+                               o.podQuery = "."
+                               o.noFollow = true
+                               o.tail = 0
+
+                               return o
+                       }(),
+                       "--no-follow cannot be used with --tail=0",
+               },
+               {
+                       "Specify --condition without --tail=0 and no 
--no-follow",
+                       func() *options {
+                               o := NewOptions(streams)
+                               o.podQuery = "."
+                               o.condition = "ready=false"
+
+                               return o
+                       }(),
+                       "--condition is currently only supported with --tail=0 
or --no-follow",
+               },
+               {
+                       "Specify --condition without --no-follow and no 
--tail=0",
+                       func() *options {
+                               o := NewOptions(streams)
+                               o.podQuery = "."
+                               o.condition = "ready=false"
+
+                               return o
+                       }(),
+                       "--condition is currently only supported with --tail=0 
or --no-follow",
                },
                {
                        "Use prompt",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/go.mod new/stern-1.32.0/go.mod
--- old/stern-1.31.0/go.mod     2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/go.mod     2025-01-21 02:14:50.000000000 +0100
@@ -1,30 +1,28 @@
 module github.com/stern/stern
 
-go 1.23
-
-toolchain go1.23.2
+go 1.23.5
 
 require (
        github.com/AlecAivazis/survey/v2 v2.3.7
-       github.com/fatih/color v1.17.0
+       github.com/fatih/color v1.18.0
        github.com/mitchellh/go-homedir v1.1.0
        github.com/pkg/errors v0.9.1
-       github.com/spf13/cast v1.7.0
+       github.com/spf13/cast v1.7.1
        github.com/spf13/cobra v1.8.1
        github.com/spf13/pflag v1.0.5
-       golang.org/x/sync v0.8.0
-       golang.org/x/time v0.7.0
+       golang.org/x/sync v0.10.0
+       golang.org/x/time v0.9.0
        gopkg.in/yaml.v3 v3.0.1
-       k8s.io/api v0.31.1
-       k8s.io/apimachinery v0.31.1
-       k8s.io/cli-runtime v0.31.1
-       k8s.io/client-go v0.31.1
+       k8s.io/api v0.32.1
+       k8s.io/apimachinery v0.32.1
+       k8s.io/cli-runtime v0.32.1
+       k8s.io/client-go v0.32.1
        k8s.io/klog/v2 v2.130.1
-       k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
+       k8s.io/utils v0.0.0-20241210054802-24370beab758
 )
 
 require (
-       github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // 
indirect
+       github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // 
indirect
        github.com/blang/semver/v4 v4.0.0 // indirect
        github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 
indirect
        github.com/emicklei/go-restful/v3 v3.12.1 // indirect
@@ -37,23 +35,22 @@
        github.com/gogo/protobuf v1.3.2 // indirect
        github.com/golang/protobuf v1.5.4 // indirect
        github.com/google/btree v1.1.3 // indirect
-       github.com/google/gnostic-models v0.6.8 // indirect
+       github.com/google/gnostic-models v0.6.9 // indirect
        github.com/google/go-cmp v0.6.0 // indirect
        github.com/google/gofuzz v1.2.0 // indirect
        github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
        github.com/google/uuid v1.6.0 // indirect
        github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // 
indirect
-       github.com/imdario/mergo v0.3.16 // indirect
        github.com/inconshreveable/mousetrap v1.1.0 // indirect
        github.com/josharian/intern v1.0.0 // indirect
        github.com/json-iterator/go v1.1.12 // indirect
        github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // 
indirect
        github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // 
indirect
-       github.com/mailru/easyjson v0.7.7 // indirect
-       github.com/mattn/go-colorable v0.1.13 // indirect
+       github.com/mailru/easyjson v0.9.0 // indirect
+       github.com/mattn/go-colorable v0.1.14 // indirect
        github.com/mattn/go-isatty v0.0.20 // indirect
        github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
-       github.com/moby/term v0.5.0 // indirect
+       github.com/moby/term v0.5.2 // indirect
        github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // 
indirect
        github.com/modern-go/reflect2 v1.0.2 // indirect
        github.com/monochromegane/go-gitignore 
v0.0.0-20200626010858-205db1a8cc00 // indirect
@@ -61,20 +58,18 @@
        github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
        github.com/x448/float16 v0.8.4 // indirect
        github.com/xlab/treeprint v1.2.0 // indirect
-       go.starlark.net v0.0.0-20240925182052-1207426daebd // indirect
-       golang.org/x/net v0.30.0 // indirect
-       golang.org/x/oauth2 v0.23.0 // indirect
-       golang.org/x/sys v0.26.0 // indirect
-       golang.org/x/term v0.25.0 // indirect
-       golang.org/x/text v0.19.0 // indirect
-       google.golang.org/protobuf v1.34.2 // indirect
+       golang.org/x/net v0.34.0 // indirect
+       golang.org/x/oauth2 v0.25.0 // indirect
+       golang.org/x/sys v0.29.0 // indirect
+       golang.org/x/term v0.28.0 // indirect
+       golang.org/x/text v0.21.0 // indirect
+       google.golang.org/protobuf v1.36.3 // indirect
        gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
        gopkg.in/inf.v0 v0.9.1 // indirect
-       gopkg.in/yaml.v2 v2.4.0 // indirect
-       k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect
-       sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
-       sigs.k8s.io/kustomize/api v0.17.3 // indirect
-       sigs.k8s.io/kustomize/kyaml v0.17.2 // indirect
-       sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+       k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
+       sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
+       sigs.k8s.io/kustomize/api v0.19.0 // indirect
+       sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect
+       sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
        sigs.k8s.io/yaml v1.4.0 // indirect
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/go.sum new/stern-1.32.0/go.sum
--- old/stern-1.31.0/go.sum     2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/go.sum     2025-01-21 02:14:50.000000000 +0100
@@ -1,7 +1,7 @@
 github.com/AlecAivazis/survey/v2 v2.3.7 
h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
 github.com/AlecAivazis/survey/v2 v2.3.7/go.mod 
h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
-github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 
h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
-github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod 
h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c 
h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod 
h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 
h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
 github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod 
h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
 github.com/blang/semver/v4 v4.0.0 
h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -16,8 +16,8 @@
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/emicklei/go-restful/v3 v3.12.1 
h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
 github.com/emicklei/go-restful/v3 v3.12.1/go.mod 
h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
-github.com/fatih/color v1.17.0/go.mod 
h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod 
h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
 github.com/frankban/quicktest v1.14.6 
h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
 github.com/frankban/quicktest v1.14.6/go.mod 
h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fxamacker/cbor/v2 v2.7.0 
h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
@@ -40,16 +40,16 @@
 github.com/golang/protobuf v1.5.4/go.mod 
h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
 github.com/google/btree v1.1.3/go.mod 
h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
-github.com/google/gnostic-models v0.6.8 
h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
-github.com/google/gnostic-models v0.6.8/go.mod 
h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/gnostic-models v0.6.9 
h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
+github.com/google/gnostic-models v0.6.9/go.mod 
h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
 github.com/google/go-cmp v0.5.9/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0/go.mod 
h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod 
h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 
h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod 
h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
+github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db 
h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
+github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod 
h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 
h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod 
h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -58,8 +58,6 @@
 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod 
h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec 
h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
 github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod 
h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
-github.com/imdario/mergo v0.3.16 
h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
-github.com/imdario/mergo v0.3.16/go.mod 
h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/inconshreveable/mousetrap v1.1.0 
h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod 
h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/josharian/intern v1.0.0 
h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -76,13 +74,12 @@
 github.com/kr/text v0.2.0/go.mod 
h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de 
h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
 github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod 
h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
-github.com/mailru/easyjson v0.7.7 
h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod 
h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.9.0 
h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
+github.com/mailru/easyjson v0.9.0/go.mod 
h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
 github.com/mattn/go-colorable v0.1.2/go.mod 
h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.13 
h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod 
h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-colorable v0.1.14 
h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod 
h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
 github.com/mattn/go-isatty v0.0.8/go.mod 
h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.16/go.mod 
h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.20 
h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod 
h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod 
h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
@@ -90,8 +87,8 @@
 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod 
h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
 github.com/mitchellh/go-homedir v1.1.0 
h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod 
h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
-github.com/moby/term v0.5.0/go.mod 
h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod 
h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod 
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd 
h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod 
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -101,10 +98,10 @@
 github.com/monochromegane/go-gitignore 
v0.0.0-20200626010858-205db1a8cc00/go.mod 
h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 
h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod 
h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.19.0 
h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
-github.com/onsi/ginkgo/v2 v2.19.0/go.mod 
h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
-github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
-github.com/onsi/gomega v1.33.1/go.mod 
h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
+github.com/onsi/ginkgo/v2 v2.21.0 
h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
+github.com/onsi/ginkgo/v2 v2.21.0/go.mod 
h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
+github.com/onsi/gomega v1.35.1/go.mod 
h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/peterbourgon/diskv v2.0.1+incompatible 
h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod 
h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -117,15 +114,15 @@
 github.com/russross/blackfriday/v2 v2.1.0/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/sergi/go-diff v1.2.0/go.mod 
h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
-github.com/spf13/cast v1.7.0/go.mod 
h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod 
h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
 github.com/spf13/cobra v1.8.1/go.mod 
h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod 
h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
-github.com/stretchr/objx v0.5.0/go.mod 
h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod 
h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.3.0/go.mod 
h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.6.1/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -138,8 +135,6 @@
 github.com/yuin/goldmark v1.1.27/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.4.13/go.mod 
h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.starlark.net v0.0.0-20240925182052-1207426daebd 
h1:S+EMisJOHklQxnS3kqsY8jl2y5aF0FDEdcLnOw3q22E=
-go.starlark.net v0.0.0-20240925182052-1207426daebd/go.mod 
h1:YKMCv9b1WrfWmeqdV5MAuEHWsu5iC+fe6kYl2sQjdI8=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod 
h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod 
h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -155,16 +150,16 @@
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod 
h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod 
h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod 
h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
-golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
-golang.org/x/oauth2 v0.23.0/go.mod 
h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
+golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
+golang.org/x/oauth2 v0.25.0/go.mod 
h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod 
h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -174,35 +169,34 @@
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
-golang.org/x/term v0.25.0/go.mod 
h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod 
h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod 
h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
-golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
-golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod 
h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
+golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod 
h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod 
h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod 
h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.12/go.mod 
h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
-golang.org/x/tools v0.24.0/go.mod 
h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
+golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
+golang.org/x/tools v0.26.0/go.mod 
h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/protobuf v1.34.2 
h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod 
h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+google.golang.org/protobuf v1.36.3 
h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod 
h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c 
h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod 
h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -210,33 +204,30 @@
 gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod 
h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod 
h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
-k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
-k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
-k8s.io/apimachinery v0.31.1/go.mod 
h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
-k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk=
-k8s.io/cli-runtime v0.31.1/go.mod 
h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U=
-k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
-k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod 
h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/cli-runtime v0.32.1 h1:19nwZPlYGJPUDbhAxDIS2/oydCikvKMHsxroKNGA2mM=
+k8s.io/cli-runtime v0.32.1/go.mod 
h1:NJPbeadVFnV2E7B7vF+FvU09mpwYlZCu8PqjzfuOnkY=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 
h1:1dWzkmJrrprYvjGwh9kEUxmcUV/CtNU8QM7h1FLWQOo=
-k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38/go.mod 
h1:coRQXBK9NxO98XUv3ZD6AK3xzHCxV6+b7lrquKwaKzA=
-k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 
h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI=
-k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod 
h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd 
h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod 
h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
-sigs.k8s.io/kustomize/api v0.17.3 
h1:6GCuHSsxq7fN5yhF2XrC+AAr8gxQwhexgHflOAD/JJU=
-sigs.k8s.io/kustomize/api v0.17.3/go.mod 
h1:TuDH4mdx7jTfK61SQ/j1QZM/QWR+5rmEiNjvYlhzFhc=
-sigs.k8s.io/kustomize/kyaml v0.17.2 
h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0=
-sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod 
h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1 
h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
-sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod 
h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
+k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 
h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
+k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod 
h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
+k8s.io/utils v0.0.0-20241210054802-24370beab758 
h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
+k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod 
h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 
h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
+sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod 
h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
+sigs.k8s.io/kustomize/api v0.19.0 
h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
+sigs.k8s.io/kustomize/api v0.19.0/go.mod 
h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=
+sigs.k8s.io/kustomize/kyaml v0.19.0 
h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=
+sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod 
h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0 
h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
+sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod 
h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/condition.go 
new/stern-1.32.0/stern/condition.go
--- old/stern-1.31.0/stern/condition.go 1970-01-01 01:00:00.000000000 +0100
+++ new/stern-1.32.0/stern/condition.go 2025-01-21 02:14:50.000000000 +0100
@@ -0,0 +1,89 @@
+package stern
+
+import (
+       "fmt"
+       "strings"
+
+       v1 "k8s.io/api/core/v1"
+)
+
+type Condition struct {
+       Name  v1.PodConditionType
+       Value v1.ConditionStatus
+}
+
+// NewCondition returns a Condition struct for a given conditionString
+func NewCondition(conditionString string) (Condition, error) {
+       // condition can be: condition-name or condition-name=condition-value
+       conditionNameString := strings.ToLower(conditionString)
+       conditionValueString := "true"
+       if equalsIndex := strings.Index(conditionNameString, "="); equalsIndex 
!= -1 {
+               conditionValueString = conditionNameString[equalsIndex+1:]
+               conditionNameString = conditionNameString[0:equalsIndex]
+       }
+
+       var conditionName v1.PodConditionType
+
+       validConditions := []v1.PodConditionType{
+               v1.ContainersReady,
+               v1.PodInitialized,
+               v1.PodReady,
+               v1.PodScheduled,
+               v1.DisruptionTarget,
+               v1.PodReadyToStartContainers,
+       }
+
+       for _, validCondition := range validConditions {
+               if strings.ToLower(string(validCondition)) == 
conditionNameString {
+                       conditionName = validCondition
+                       break
+               }
+       }
+
+       if conditionName == "" {
+               validConditionsStrings := make([]string, len(validConditions))
+               for i, val := range validConditions {
+                       validConditionsStrings[i] = string(val)
+               }
+               return Condition{}, fmt.Errorf("condition should be one of 
'%s'", strings.Join(validConditionsStrings, "', '"))
+       }
+
+       var conditionValue v1.ConditionStatus
+
+       validValues := []v1.ConditionStatus{
+               v1.ConditionTrue,
+               v1.ConditionFalse,
+               v1.ConditionUnknown,
+       }
+
+       for _, validValue := range validValues {
+               if strings.ToLower(string(validValue)) == conditionValueString {
+                       conditionValue = validValue
+                       break
+               }
+       }
+
+       if conditionValue == "" {
+               validValuesStrings := make([]string, len(validValues))
+               for i, val := range validValues {
+                       validValuesStrings[i] = string(val)
+               }
+               return Condition{}, fmt.Errorf("condition value should be one 
of '%s'", strings.Join(validValuesStrings, "', '"))
+       }
+
+       return Condition{
+               Name:  conditionName,
+               Value: conditionValue,
+       }, nil
+}
+
+// Match returns if pod matches the condition
+func (conditionConfig Condition) Match(podConditions []v1.PodCondition) bool {
+       for _, condition := range podConditions {
+               if condition.Type == conditionConfig.Name {
+                       return condition.Status == conditionConfig.Value
+               }
+       }
+
+       return false
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/condition_test.go 
new/stern-1.32.0/stern/condition_test.go
--- old/stern-1.31.0/stern/condition_test.go    1970-01-01 01:00:00.000000000 
+0100
+++ new/stern-1.32.0/stern/condition_test.go    2025-01-21 02:14:50.000000000 
+0100
@@ -0,0 +1,126 @@
+package stern
+
+import (
+       "testing"
+
+       v1 "k8s.io/api/core/v1"
+)
+
+func TestNewCondition(t *testing.T) {
+       tests := []struct {
+               conditionString string
+               expected        Condition
+               isError         bool
+       }{
+               {
+                       "Ready",
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionTrue,
+                       },
+                       false,
+               },
+               {
+                       "ready=true",
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionTrue,
+                       },
+                       false,
+               },
+               {
+                       "Ready=False",
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionFalse,
+                       },
+                       false,
+               },
+               {
+                       "ready=Unknown",
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionUnknown,
+                       },
+                       false,
+               },
+               {
+                       "beautiful",
+                       Condition{},
+                       true,
+               },
+               {
+                       "ready=NotYet",
+                       Condition{},
+                       true,
+               },
+       }
+
+       for i, tt := range tests {
+               condition, err := NewCondition(tt.conditionString)
+
+               if tt.expected != condition {
+                       t.Errorf("%d: expected %v, but actual %v", i, 
tt.expected, condition)
+               }
+
+               if (tt.isError && err == nil) || (!tt.isError && err != nil) {
+                       t.Errorf("%d: expected error is %v, but actual %v", i, 
tt.isError, err)
+               }
+       }
+}
+
+func TestConditionMatch(t *testing.T) {
+       tests := []struct {
+               condition       Condition
+               v1PodConditions []v1.PodCondition
+               expected        bool
+       }{
+               {
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionTrue,
+                       },
+                       []v1.PodCondition{
+                               {
+                                       Type:   v1.PodReady,
+                                       Status: v1.ConditionTrue,
+                               },
+                       },
+                       true,
+               },
+               {
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionTrue,
+                       },
+                       []v1.PodCondition{
+                               {
+                                       Type:   v1.PodReady,
+                                       Status: v1.ConditionFalse,
+                               },
+                       },
+                       false,
+               },
+               {
+                       Condition{
+                               Name:  v1.PodReady,
+                               Value: v1.ConditionTrue,
+                       },
+                       []v1.PodCondition{
+                               {
+                                       Type:   v1.PodInitialized,
+                                       Status: v1.ConditionFalse,
+                               },
+                       },
+                       false,
+               },
+       }
+
+       for i, tt := range tests {
+               actual := tt.condition.Match(tt.v1PodConditions)
+
+               if tt.expected != actual {
+                       t.Errorf("%d: expected %v, but actual %v", i, 
tt.expected, actual)
+               }
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/config.go 
new/stern-1.32.0/stern/config.go
--- old/stern-1.31.0/stern/config.go    2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/config.go    2025-01-21 02:14:50.000000000 +0100
@@ -34,6 +34,7 @@
        Location              *time.Location
        ContainerQuery        *regexp.Regexp
        ExcludeContainerQuery []*regexp.Regexp
+       Condition             Condition
        ContainerStates       []ContainerState
        Exclude               []*regexp.Regexp
        Include               []*regexp.Regexp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/container_state_test.go 
new/stern-1.32.0/stern/container_state_test.go
--- old/stern-1.31.0/stern/container_state_test.go      2024-10-07 
11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/container_state_test.go      2025-01-21 
02:14:50.000000000 +0100
@@ -52,7 +52,7 @@
        }
 }
 
-func TestMatch(t *testing.T) {
+func TestContainerStateMatch(t *testing.T) {
        tests := []struct {
                containerState   ContainerState
                v1ContainerState v1.ContainerState
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/list.go 
new/stern-1.32.0/stern/list.go
--- old/stern-1.31.0/stern/list.go      2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/list.go      2025-01-21 02:14:50.000000000 +0100
@@ -79,8 +79,10 @@
        }
        var targets []*Target
        for i := range list.Items {
-               filter.visit(&list.Items[i], func(t *Target) {
-                       targets = append(targets, t)
+               filter.visit(&list.Items[i], func(t *Target, conditionFound 
bool) {
+                       if conditionFound {
+                               targets = append(targets, t)
+                       }
                })
        }
        return targets, nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/stern.go 
new/stern-1.32.0/stern/stern.go
--- old/stern-1.31.0/stern/stern.go     2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/stern.go     2025-01-21 02:14:50.000000000 +0100
@@ -20,6 +20,7 @@
        "os"
        "regexp"
        "strings"
+       "sync"
        "time"
 
        "sync/atomic"
@@ -99,6 +100,7 @@
                excludePodFilter:       config.ExcludePodQuery,
                containerFilter:        config.ContainerQuery,
                containerExcludeFilter: config.ExcludeContainerQuery,
+               condition:              config.Condition,
                initContainers:         config.InitContainers,
                ephemeralContainers:    config.EphemeralContainers,
                containerStates:        config.ContainerStates,
@@ -166,6 +168,7 @@
                }
        }
 
+       cancelMap := sync.Map{}
        eg, nctx := errgroup.WithContext(ctx)
        var numRequests atomic.Int64
        for _, n := range namespaces {
@@ -173,7 +176,7 @@
                if err != nil {
                        return err
                }
-               a, err := WatchTargets(nctx,
+               a, d, err := WatchTargets(nctx,
                        client.CoreV1().Pods(n),
                        selector,
                        config.FieldSelector,
@@ -197,10 +200,18 @@
                                                                " use 
--max-log-requests to increase the limit",
                                                        config.MaxLogRequests)
                                        }
+                                       ctx, cancel := context.WithCancel(nctx)
+                                       cancelMap.Store(target.GetID(), cancel)
                                        go func() {
-                                               tailTarget(nctx, target)
+                                               tailTarget(ctx, target)
                                                numRequests.Add(-1)
+                                               cancel()
+                                               cancelMap.Delete(target.GetID())
                                        }()
+                               case target := <-d:
+                                       if cancel, ok := 
cancelMap.LoadAndDelete(target.GetID()); ok {
+                                               cancel.(context.CancelFunc)()
+                                       }
                                case <-nctx.Done():
                                        return nil
                                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/target.go 
new/stern-1.32.0/stern/target.go
--- old/stern-1.31.0/stern/target.go    2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/target.go    2025-01-21 02:14:50.000000000 +0100
@@ -54,6 +54,7 @@
        excludePodFilter       []*regexp.Regexp
        containerFilter        *regexp.Regexp
        containerExcludeFilter []*regexp.Regexp
+       condition              Condition
        initContainers         bool
        ephemeralContainers    bool
        containerStates        []ContainerState
@@ -67,7 +68,7 @@
 }
 
 // visit passes filtered Targets to the visitor function
-func (f *targetFilter) visit(pod *corev1.Pod, visitor func(t *Target)) {
+func (f *targetFilter) visit(pod *corev1.Pod, visitor func(t *Target, 
conditionFound bool)) {
        // filter by pod
        if !f.c.podFilter.MatchString(pod.Name) {
                return
@@ -79,6 +80,12 @@
                }
        }
 
+       // filter by condition
+       conditionFound := true
+       if f.c.condition != (Condition{}) {
+               conditionFound = f.c.condition.Match(pod.Status.Conditions)
+       }
+
        // filter by container statuses
        var statuses []corev1.ContainerStatus
        if f.c.initContainers {
@@ -111,8 +118,14 @@
                        Container: c.Name,
                }
 
+               if !conditionFound {
+                       visitor(t, false)
+                       f.forget(string(pod.UID))
+                       continue
+               }
+
                if f.shouldAdd(t, string(pod.UID), c) {
-                       visitor(t)
+                       visitor(t, true)
                }
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/target_test.go 
new/stern-1.32.0/stern/target_test.go
--- old/stern-1.31.0/stern/target_test.go       2024-10-07 11:23:01.000000000 
+0200
+++ new/stern-1.32.0/stern/target_test.go       2025-01-21 02:14:50.000000000 
+0100
@@ -308,7 +308,7 @@
                        actual := []Target{}
                        for _, pod := range pods {
                                filter := newTargetFilter(tt.config)
-                               filter.visit(pod, func(target *Target) {
+                               filter.visit(pod, func(target *Target, 
condition bool) {
                                        actual = append(actual, *target)
                                })
                        }
@@ -417,7 +417,7 @@
                                filter.forget("uid1")
                        }
                        actual := []Target{}
-                       filter.visit(createPod(tt.cs), func(target *Target) {
+                       filter.visit(createPod(tt.cs), func(target *Target, 
condition bool) {
                                actual = append(actual, *target)
                        })
                        if !reflect.DeepEqual(tt.expected, actual) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/stern-1.31.0/stern/watch.go 
new/stern-1.32.0/stern/watch.go
--- old/stern-1.31.0/stern/watch.go     2024-10-07 11:23:01.000000000 +0200
+++ new/stern-1.32.0/stern/watch.go     2025-01-21 02:14:50.000000000 +0100
@@ -31,7 +31,7 @@
 
 // Watch starts listening to Kubernetes events and emits modified
 // containers/pods. The result is targets added.
-func WatchTargets(ctx context.Context, i v1.PodInterface, labelSelector 
labels.Selector, fieldSelector fields.Selector, filter *targetFilter) (chan 
*Target, error) {
+func WatchTargets(ctx context.Context, i v1.PodInterface, labelSelector 
labels.Selector, fieldSelector fields.Selector, filter *targetFilter) (added, 
deleted chan *Target, err error) {
        // RetryWatcher will make sure that in case the underlying watcher is
        // closed (e.g. due to API timeout or etcd timeout) it will get 
restarted
        // from the last point without the consumer even knowing about it.
@@ -41,10 +41,11 @@
                },
        })
        if err != nil {
-               return nil, errors.Wrap(err, "failed to create a watcher")
+               return nil, nil, errors.Wrap(err, "failed to create a watcher")
        }
 
-       added := make(chan *Target)
+       added = make(chan *Target)
+       deleted = make(chan *Target)
        go func() {
                for {
                        select {
@@ -62,8 +63,12 @@
 
                                switch e.Type {
                                case watch.Added, watch.Modified:
-                                       filter.visit(pod, func(t *Target) {
-                                               added <- t
+                                       filter.visit(pod, func(t *Target, 
conditionFound bool) {
+                                               if conditionFound {
+                                                       added <- t
+                                               } else {
+                                                       deleted <- t
+                                               }
                                        })
                                case watch.Deleted:
                                        filter.forget(string(pod.UID))
@@ -76,5 +81,5 @@
                }
        }()
 
-       return added, nil
+       return added, deleted, nil
 }

++++++ stern.obsinfo ++++++
--- /var/tmp/diff_new_pack.90MIeQ/_old  2025-01-27 20:59:00.291909376 +0100
+++ /var/tmp/diff_new_pack.90MIeQ/_new  2025-01-27 20:59:00.295909541 +0100
@@ -1,5 +1,5 @@
 name: stern
-version: 1.31.0
-mtime: 1728292981
-commit: ae7a33d6fbe59f08be9252f45b94b64fc6ab0281
+version: 1.32.0
+mtime: 1737422090
+commit: 5e06930fe21f951f079880ec2c13cd688aa5ca09
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/stern/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.stern.new.2316/vendor.tar.gz differ: char 5, line 1

Reply via email to