CCXDEV-8768: Add a new conditional gatherer for CRs under the alert namespace#1308
Conversation
|
@ncaak: This pull request references CCXDEV-8768 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
📝 WalkthroughWalkthroughTwo conditional gatherers are extended: a new ChangesConditional gatherers
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 15✅ Passed checks (15 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ncaak The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/hold |
|
/retest |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
pkg/gatherers/conditional/gather_cr_definition_test.go (1)
43-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRename the test to match the repository's Go test convention.
TestGatherer_gatherCRDefinitiondoes not follow the requiredTest_<FunctionName>/Test_<GatherName>_<FunctionName>form.Suggested rename
-func TestGatherer_gatherCRDefinition(t *testing.T) { +func Test_Gatherer_gatherCRDefinition(t *testing.T) {As per coding guidelines,
**/*_test.go: "Name test functions asTest_<FunctionName>orTest_<GatherName>_<FunctionName>."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/gatherers/conditional/gather_cr_definition_test.go` at line 43, Rename the test function TestGatherer_gatherCRDefinition to follow the Go test naming convention used in this repo, using the Test_<GatherName>_<FunctionName> pattern. Update the declaration in gather_cr_definition_test.go so the test name clearly matches the gatherer and method under test, and keep the rest of the test logic unchanged.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/gatherers/conditional/gather_cr_definition.go`:
- Around line 75-109: The namespace-based CR listing in the alertInstances loop
can emit duplicate records when multiple alert instances resolve to the same
namespace. Update gather_cr_definition.go to deduplicate namespaces before
calling dynamicClient.Resource(gvr).Namespace(namespace).List, then iterate the
unique namespace set and keep the existing record creation logic in the inner CR
list loop. Use getAlertPodNamespace, dynamicClient.Resource, and the
record.Record path builder as the key locations to adjust.
In `@pkg/gatherers/conditional/gather_pod_definition.go`:
- Around line 88-99: The empty-prefix fallback in gather_pod_definition.go is
currently unreachable because the gathering_rule.schema.json contract makes
pod_prefix required and non-empty. Update the schema and runtime behavior to
match: either make pod_prefix optional or relax its validation to allow an empty
string, and ensure GatherPodDefinition/related prefix handling still behaves
correctly when params.PodPrefix is absent or blank.
- Around line 90-94: The pod gathering flow in gatherPodDefinition should not
return immediately when coreClient.Pods(...).List fails for a single namespace.
Update the error handling to append the list error to errs, preserve any already
collected records, and continue processing the remaining alert instances instead
of exiting early. Keep the logic in gatherPodDefinition and the pod listing loop
intact, but ensure partial results are returned even when one namespace lookup
fails.
In `@pkg/gatherers/conditional/gathering_rule.schema.json`:
- Around line 252-255: The `resource` field in `cr_definition` is too
restrictive because `gathering_rule.schema.json` only allows lowercase letters
and digits, which rejects valid hyphenated CR resource names. Update the schema
pattern for the `resource` property so it accepts hyphens as well, and keep the
change scoped to the `cr_definition` validation path used by the new gatherer.
- Around line 210-223: The `pod_definition` schema in
`gathering_rule.schema.json` is too strict for existing `validation.go` behavior
and current rule usage. Update the `required` fields and `pod_prefix` validation
so `alert_name`-only rules are accepted, and relax the `pod_prefix` pattern in
the `properties.pod_prefix` definition to allow controller-generated prefixes
like `alertmanager-main-` instead of only full DNS labels. Keep the schema
aligned with how `validation.go` validates rules at runtime and use the existing
`pod_definition`/`pod_prefix` symbols to locate the change.
---
Nitpick comments:
In `@pkg/gatherers/conditional/gather_cr_definition_test.go`:
- Line 43: Rename the test function TestGatherer_gatherCRDefinition to follow
the Go test naming convention used in this repo, using the
Test_<GatherName>_<FunctionName> pattern. Update the declaration in
gather_cr_definition_test.go so the test name clearly matches the gatherer and
method under test, and keep the rest of the test logic unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: c37c5a6d-30d6-4548-959a-10542f41b47f
📒 Files selected for processing (8)
docs/gathered-data.mddocs/insights-archive-sample/conditional/namespaces/openshift-storage/crd/ceph.rook.io/v1/cephclusters/ocs-storagecluster-cephcluster.jsonpkg/gatherers/conditional/gather_cr_definition.gopkg/gatherers/conditional/gather_cr_definition_test.gopkg/gatherers/conditional/gather_pod_definition.gopkg/gatherers/conditional/gather_pod_definition_test.gopkg/gatherers/conditional/gathering_functions.gopkg/gatherers/conditional/gathering_rule.schema.json
| for _, alertLabels := range alertInstances { | ||
| namespace, err := getAlertPodNamespace(alertLabels) | ||
| if err != nil { | ||
| klog.Warningf(logMissingLabel, err.Error(), params.AlertName) | ||
| errs = append(errs, err) | ||
| continue | ||
| } | ||
|
|
||
| gvr := schema.GroupVersionResource{ | ||
| Group: params.Group, | ||
| Version: params.Version, | ||
| Resource: params.Resource, | ||
| } | ||
|
|
||
| crList, err := dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{}) | ||
| if err != nil { | ||
| klog.Warningf("CR not found in %s namespace (GVR: %v): %v", namespace, gvr, err) | ||
| errs = append(errs, err) | ||
| continue | ||
| } | ||
|
|
||
| for i := range crList.Items { | ||
| item := &crList.Items[i] | ||
| records = append(records, record.Record{ | ||
| Name: fmt.Sprintf( | ||
| "%s/namespaces/%s/crd/%s/%s/%s/%s", | ||
| g.GetName(), | ||
| namespace, | ||
| params.Group, | ||
| params.Version, | ||
| params.Resource, | ||
| item.GetName()), | ||
| Item: record.JSONMarshaller{Object: item.Object}, | ||
| }) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Deduplicate namespaces before listing CRs.
If the same alert fires for multiple objects in one namespace, this loop lists the same GVR once per alert instance and emits the same archive paths repeatedly. That produces duplicate conditional/namespaces/<ns>/crd/... records for a single namespace.
Suggested fix
var errs []error
var records []record.Record
+ seenNamespaces := map[string]struct{}{}
for _, alertLabels := range alertInstances {
namespace, err := getAlertPodNamespace(alertLabels)
if err != nil {
klog.Warningf(logMissingLabel, err.Error(), params.AlertName)
errs = append(errs, err)
continue
}
+ if _, seen := seenNamespaces[namespace]; seen {
+ continue
+ }
+ seenNamespaces[namespace] = struct{}{}
gvr := schema.GroupVersionResource{
Group: params.Group,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for _, alertLabels := range alertInstances { | |
| namespace, err := getAlertPodNamespace(alertLabels) | |
| if err != nil { | |
| klog.Warningf(logMissingLabel, err.Error(), params.AlertName) | |
| errs = append(errs, err) | |
| continue | |
| } | |
| gvr := schema.GroupVersionResource{ | |
| Group: params.Group, | |
| Version: params.Version, | |
| Resource: params.Resource, | |
| } | |
| crList, err := dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{}) | |
| if err != nil { | |
| klog.Warningf("CR not found in %s namespace (GVR: %v): %v", namespace, gvr, err) | |
| errs = append(errs, err) | |
| continue | |
| } | |
| for i := range crList.Items { | |
| item := &crList.Items[i] | |
| records = append(records, record.Record{ | |
| Name: fmt.Sprintf( | |
| "%s/namespaces/%s/crd/%s/%s/%s/%s", | |
| g.GetName(), | |
| namespace, | |
| params.Group, | |
| params.Version, | |
| params.Resource, | |
| item.GetName()), | |
| Item: record.JSONMarshaller{Object: item.Object}, | |
| }) | |
| } | |
| var errs []error | |
| var records []record.Record | |
| seenNamespaces := map[string]struct{}{} | |
| for _, alertLabels := range alertInstances { | |
| namespace, err := getAlertPodNamespace(alertLabels) | |
| if err != nil { | |
| klog.Warningf(logMissingLabel, err.Error(), params.AlertName) | |
| errs = append(errs, err) | |
| continue | |
| } | |
| if _, seen := seenNamespaces[namespace]; seen { | |
| continue | |
| } | |
| seenNamespaces[namespace] = struct{}{} | |
| gvr := schema.GroupVersionResource{ | |
| Group: params.Group, | |
| Version: params.Version, | |
| Resource: params.Resource, | |
| } | |
| crList, err := dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{}) | |
| if err != nil { | |
| klog.Warningf("CR not found in %s namespace (GVR: %v): %v", namespace, gvr, err) | |
| errs = append(errs, err) | |
| continue | |
| } | |
| for i := range crList.Items { | |
| item := &crList.Items[i] | |
| records = append(records, record.Record{ | |
| Name: fmt.Sprintf( | |
| "%s/namespaces/%s/crd/%s/%s/%s/%s", | |
| g.GetName(), | |
| namespace, | |
| params.Group, | |
| params.Version, | |
| params.Resource, | |
| item.GetName()), | |
| Item: record.JSONMarshaller{Object: item.Object}, | |
| }) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/gatherers/conditional/gather_cr_definition.go` around lines 75 - 109, The
namespace-based CR listing in the alertInstances loop can emit duplicate records
when multiple alert instances resolve to the same namespace. Update
gather_cr_definition.go to deduplicate namespaces before calling
dynamicClient.Resource(gvr).Namespace(namespace).List, then iterate the unique
namespace set and keep the existing record creation logic in the inner CR list
loop. Use getAlertPodNamespace, dynamicClient.Resource, and the record.Record
path builder as the key locations to adjust.
There was a problem hiding this comment.
@ncaak I think this is a valid comment that could save a few API requests. Can you have a look?
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
| if len(params.PodPrefix) > 0 { | ||
| // New logic has been introduced to retrieve a list of pods with a given prefix (from params) | ||
| podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{}) | ||
| if err != nil { | ||
| klog.Errorf("failed to list pods in namespace %s: %v", podNamespace, err) | ||
| return nil, []error{err} | ||
| } | ||
|
|
||
| podDefinitions = filterPodsByPrefix(podList, params.PodPrefix) | ||
| // | ||
| } else { | ||
| // Previous logic to retrieve ONLY the pod definition from the firing alert |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
pod_prefix fallback is unreachable under current schema contract.
The empty-prefix branch is implemented here, but pkg/gatherers/conditional/gathering_rule.schema.json:207-225 marks pod_prefix as required with a non-empty regex, so validated configs cannot hit this fallback path. Align schema and runtime behavior (make pod_prefix optional or allow empty string).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/gatherers/conditional/gather_pod_definition.go` around lines 88 - 99, The
empty-prefix fallback in gather_pod_definition.go is currently unreachable
because the gathering_rule.schema.json contract makes pod_prefix required and
non-empty. Update the schema and runtime behavior to match: either make
pod_prefix optional or relax its validation to allow an empty string, and ensure
GatherPodDefinition/related prefix handling still behaves correctly when
params.PodPrefix is absent or blank.
| podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{}) | ||
| if err != nil { | ||
| klog.Errorf("failed to list pods in namespace %s: %v", podNamespace, err) | ||
| return nil, []error{err} | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Avoid aborting the whole gather on a single namespace list failure.
Line 93 returns immediately, which discards already collected records/errs and skips remaining alert instances. Keep partial results and continue.
Suggested fix
- podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{})
+ podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{})
if err != nil {
klog.Errorf("failed to list pods in namespace %s: %v", podNamespace, err)
- return nil, []error{err}
+ errs = append(errs, err)
+ continue
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{}) | |
| if err != nil { | |
| klog.Errorf("failed to list pods in namespace %s: %v", podNamespace, err) | |
| return nil, []error{err} | |
| } | |
| podList, err := coreClient.Pods(podNamespace).List(ctx, metav1.ListOptions{}) | |
| if err != nil { | |
| klog.Errorf("failed to list pods in namespace %s: %v", podNamespace, err) | |
| errs = append(errs, err) | |
| continue | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/gatherers/conditional/gather_pod_definition.go` around lines 90 - 94, The
pod gathering flow in gatherPodDefinition should not return immediately when
coreClient.Pods(...).List fails for a single namespace. Update the error
handling to append the list error to errs, preserve any already collected
records, and continue processing the remaining alert instances instead of
exiting early. Keep the logic in gatherPodDefinition and the pod listing loop
intact, but ensure partial results are returned even when one namespace lookup
fails.
| "required": [ | ||
| "alert_name" | ||
| "alert_name", | ||
| "pod_prefix" | ||
| ], | ||
| "properties": { | ||
| "alert_name": { | ||
| "type": "string", | ||
| "title": "AlertName", | ||
| "pattern": "^[a-zA-Z0-9_]{1,128}$" | ||
| }, | ||
| "pod_prefix": { | ||
| "type": "string", | ||
| "title": "PodPrefix", | ||
| "pattern": "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Relax the pod_definition schema before this becomes the contract.
validation.go enforces this schema before runtime, so requiring pod_prefix rejects existing alert_name-only rules outright. The current regex also only accepts a complete DNS label, not common prefixes like alertmanager-main-, which is exactly what this feature needs for controller-generated pod names.
Suggested schema change
"^pod_definition$": {
"type": "object",
"title": "GatherPodDefinitionParams",
"required": [
- "alert_name",
- "pod_prefix"
+ "alert_name"
],
"properties": {
"alert_name": {
"type": "string",
"title": "AlertName",
"pattern": "^[a-zA-Z0-9_]{1,128}$"
},
"pod_prefix": {
"type": "string",
"title": "PodPrefix",
- "pattern": "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
+ "minLength": 1,
+ "maxLength": 253,
+ "pattern": "^[a-z0-9][a-z0-9.-]{0,252}$"
}
}
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "required": [ | |
| "alert_name" | |
| "alert_name", | |
| "pod_prefix" | |
| ], | |
| "properties": { | |
| "alert_name": { | |
| "type": "string", | |
| "title": "AlertName", | |
| "pattern": "^[a-zA-Z0-9_]{1,128}$" | |
| }, | |
| "pod_prefix": { | |
| "type": "string", | |
| "title": "PodPrefix", | |
| "pattern": "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$" | |
| "required": [ | |
| "alert_name" | |
| ], | |
| "properties": { | |
| "alert_name": { | |
| "type": "string", | |
| "title": "AlertName", | |
| "pattern": "^[a-zA-Z0-9_]{1,128}$" | |
| }, | |
| "pod_prefix": { | |
| "type": "string", | |
| "title": "PodPrefix", | |
| "minLength": 1, | |
| "maxLength": 253, | |
| "pattern": "^[a-z0-9][a-z0-9.-]{0,252}$" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/gatherers/conditional/gathering_rule.schema.json` around lines 210 - 223,
The `pod_definition` schema in `gathering_rule.schema.json` is too strict for
existing `validation.go` behavior and current rule usage. Update the `required`
fields and `pod_prefix` validation so `alert_name`-only rules are accepted, and
relax the `pod_prefix` pattern in the `properties.pod_prefix` definition to
allow controller-generated prefixes like `alertmanager-main-` instead of only
full DNS labels. Keep the schema aligned with how `validation.go` validates
rules at runtime and use the existing `pod_definition`/`pod_prefix` symbols to
locate the change.
| "resource": { | ||
| "type": "string", | ||
| "title": "Resource", | ||
| "pattern": "^[a-z0-9]{1,64}$" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Allow hyphenated CR resource names in cr_definition.
The resource pattern only permits [a-z0-9], so valid plural resources such as network-attachment-definitions are rejected during schema validation and can never reach the new gatherer.
Suggested schema change
"resource": {
"type": "string",
"title": "Resource",
- "pattern": "^[a-z0-9]{1,64}$"
+ "pattern": "^[a-z0-9]([a-z0-9-]{0,251}[a-z0-9])?$"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "resource": { | |
| "type": "string", | |
| "title": "Resource", | |
| "pattern": "^[a-z0-9]{1,64}$" | |
| "resource": { | |
| "type": "string", | |
| "title": "Resource", | |
| "pattern": "^[a-z0-9]([a-z0-9-]{0,251}[a-z0-9])?$" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/gatherers/conditional/gathering_rule.schema.json` around lines 252 - 255,
The `resource` field in `cr_definition` is too restrictive because
`gathering_rule.schema.json` only allows lowercase letters and digits, which
rejects valid hyphenated CR resource names. Update the schema pattern for the
`resource` property so it accepts hyphens as well, and keep the change scoped to
the `cr_definition` validation path used by the new gatherer.
| return nil, []error{err} | ||
| } | ||
|
|
||
| const logMissingLabel = "%s at alertName: %s" |
There was a problem hiding this comment.
Can you move this to the top of the file?
| gvr := schema.GroupVersionResource{ | ||
| Group: params.Group, | ||
| Version: params.Version, | ||
| Resource: params.Resource, | ||
| } |
There was a problem hiding this comment.
Can this be moved outside the for loop?
| for _, alertLabels := range alertInstances { | ||
| namespace, err := getAlertPodNamespace(alertLabels) | ||
| if err != nil { | ||
| klog.Warningf(logMissingLabel, err.Error(), params.AlertName) | ||
| errs = append(errs, err) | ||
| continue | ||
| } | ||
|
|
||
| gvr := schema.GroupVersionResource{ | ||
| Group: params.Group, | ||
| Version: params.Version, | ||
| Resource: params.Resource, | ||
| } | ||
|
|
||
| crList, err := dynamicClient.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{}) | ||
| if err != nil { | ||
| klog.Warningf("CR not found in %s namespace (GVR: %v): %v", namespace, gvr, err) | ||
| errs = append(errs, err) | ||
| continue | ||
| } | ||
|
|
||
| for i := range crList.Items { | ||
| item := &crList.Items[i] | ||
| records = append(records, record.Record{ | ||
| Name: fmt.Sprintf( | ||
| "%s/namespaces/%s/crd/%s/%s/%s/%s", | ||
| g.GetName(), | ||
| namespace, | ||
| params.Group, | ||
| params.Version, | ||
| params.Resource, | ||
| item.GetName()), | ||
| Item: record.JSONMarshaller{Object: item.Object}, | ||
| }) | ||
| } |
There was a problem hiding this comment.
@ncaak I think this is a valid comment that could save a few API requests. Can you have a look?
|
@ncaak: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
This PR implements a new conditional gatherer. This new gatherer will try to retrieve a CR given its GVR always under the namespace where the alert is firing.
The pod definition gatherer was also upgraded to accept a prefix in its params. If a prefix is set, the gatherer will check for all pods that matches the prefix. Always under the same namespace where the alert is firing.
Some unit tests were added to the pod definition gatherer to adapt to the new functionality.
Categories
Sample Archive
docs/insights-archive-sample/conditional/namespaces/openshift-storage/crd/ceph.rook.io/v1/cephclusters/ocs-storagecluster-cephcluster.jsonDocumentation
docs/gathered-data.mdUnit Tests
pkg/gatherers/conditional/gather_pod_definition_test.gopkg/gatherers/conditional/gather_cr_definition_test.goPrivacy
Yes. There are no sensitive data in the newly collected information.
Changelog
No
Breaking Changes
No
References
https://redhat.atlassian.net/browse/CCXDEV-8768
Summary by CodeRabbit
Release Notes
New Features
Enhancements
pod_definitionto optionally usepod_prefixto gather multiple pods from the alert namespace.pod_prefix.Documentation
Tests