Skip to content

fix(validation): allow empty sources for audit and infrastructure inputs#3323

Open
Clee2691 wants to merge 1 commit into
openshift:masterfrom
Clee2691:LOG-9541
Open

fix(validation): allow empty sources for audit and infrastructure inputs#3323
Clee2691 wants to merge 1 commit into
openshift:masterfrom
Clee2691:LOG-9541

Conversation

@Clee2691

@Clee2691 Clee2691 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Description

  • Remove validation that required at least one source for audit and infrastructure inputs — empty sources now means "all sources"
  • Guard the infrastructure container-tuning check so it only fires when sources are explicitly specified
  • Fix test Describe label in audit tests and typo in infrastructure test name

/cc @vparfonov
/assign @jcantrill

Links

Summary by CodeRabbit

  • Bug Fixes
    • Audit and infrastructure inputs now validate successfully even when no sources are explicitly provided.
    • Default reserved sources are applied automatically in those cases, improving out-of-the-box behavior.
    • Loki output generation now handles empty audit source configurations more reliably.
    • Updated related test coverage to reflect the new validation and source-selection behavior.

@openshift-ci openshift-ci Bot requested a review from vparfonov July 1, 2026 16:47
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR changes how missing or empty audit/infrastructure input sources are handled: Inputs.InputSources now falls back to reserved default source sets instead of empty results, and corresponding validations no longer fail when sources are empty. LokiStack generation and tests are updated accordingly.

Changes

Reserved source defaults and validation relaxation

Layer / File(s) Summary
Reserved source sets and InputSources logic
internal/api/observability/input_types.go, internal/api/observability/input_types_test.go
Adds ReservedAuditSources and updates Inputs.InputSources to use reserved/default sources when Infrastructure or Audit sources are nil/empty, with new tests validating both fallback and explicit-source behavior.
Validation relaxation for empty sources
internal/validations/observability/inputs/audit.go, internal/validations/observability/inputs/audit_test.go, internal/validations/observability/inputs/infrastructure.go, internal/validations/observability/inputs/infrastructure_test.go
ValidateAudit and ValidateInfrastructure no longer fail for empty sources; infrastructure tuning check is guarded by non-empty sources; tests updated to assert success for empty/nil sources and a test description typo is fixed.
LokiStack input source generation update
internal/generator/vector/output/lokistack/lokistack.go, internal/generator/vector/output/lokistack/lokistack_test.go
getInputSources removes the special-case fallback for empty infrastructure inputs and always calls addReceiverSources; a new test entry covers the OpenTelemetry data model with empty audit sources.

Estimated code review effort: 2 (Simple) | ~12 minutes

Related PRs: None identified.

Suggested labels: validation, observability, lokistack

Suggested reviewers: None identified.

🐰 A hop, a skip, an empty list—
no more failing, sources missed.
Reserved defaults now step in,
let audit and infra logs begin.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: allowing empty sources for audit and infrastructure validation.
Description check ✅ Passed The description includes the required summary, reviewer assignment, approval assignment, and a links section with a related JIRA issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@qodo-for-rh-openshift

Copy link
Copy Markdown

PR Summary by Qodo

Fix validation to allow empty sources for audit/infrastructure inputs

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Treat empty or nil audit/infrastructure sources as "all sources" during validation.
• Gate infrastructure container-tuning validation to only run when sources are explicitly set.
• Update/expand unit tests to cover empty/nil sources and fix test descriptions.
Diagram

graph TD
  A["InputSpec"] --> B["ValidateAudit"] --> C["ValidInput Condition"]
  A --> D["ValidateInfrastructure"] --> C
  D --> E{"Sources set?"} --> F["Container tuning check"]

  subgraph Legend
    direction LR
    _in["Input spec"] ~~~ _fn["Validator"] ~~~ _cond["Condition output"] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Default sources to "all" during spec defaulting
  • ➕ Keeps validation logic simpler (no special-casing empty vs non-empty)
  • ➕ Downstream consumers see an explicit, normalized list of sources
  • ➖ Requires introducing/adjusting defaulting behavior (webhook or admission/defaulting path)
  • ➖ Must define/maintain the canonical "all sources" list in one place
2. Introduce an explicit boolean like `sourcesAll: true`
  • ➕ Avoids ambiguous meaning of empty list
  • ➕ More self-documenting API semantics
  • ➖ API/schema change with compatibility and documentation burden
  • ➖ More user-facing complexity for a small behavior change

Recommendation: The PR’s approach (treat empty/nil as "all" and adjust validation accordingly) is the lowest-risk change and matches the desired semantics without API surface changes. If this pattern expands to more inputs over time, consider centralizing the "empty means all" behavior via defaulting to reduce repeated special-cases in validators.

Files changed (4) +26 / -17

Bug fix (2) +1 / -11
audit.goAllow empty audit sources during validation +0/-5

Allow empty audit sources during validation

• Removes the validation failure when 'spec.Audit.Sources' is empty. Audit inputs now validate successfully even when no sources are specified (interpreted as "all sources").

internal/validations/observability/inputs/audit.go

infrastructure.goTreat empty infrastructure sources as valid and guard tuning check +1/-6

Treat empty infrastructure sources as valid and guard tuning check

• Removes the "must define at least one source" validation. The container-tuning MaxMessageSize check now only runs when sources are explicitly provided (len > 0), avoiding false failures when empty implies "all sources".

internal/validations/observability/inputs/infrastructure.go

Tests (2) +25 / -6
audit_test.goUpdate audit validation tests for empty/nil sources +7/-3

Update audit validation tests for empty/nil sources

• Fixes the top-level Describe label to match 'ValidateAudit'. Updates the previous failure case to assert success when sources are empty and adds coverage for nil sources.

internal/validations/observability/inputs/audit_test.go

infrastructure_test.goExpand infrastructure tests for empty/nil sources and tuning guard +18/-3

Expand infrastructure tests for empty/nil sources and tuning guard

• Converts the prior empty-sources failure test into success cases for empty and nil sources, and adds a new case asserting success when sources are empty but container tuning is set. Fixes a typo in a test name.

internal/validations/observability/inputs/infrastructure_test.go

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@qodo-for-rh-openshift

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 9 rules

Grey Divider


Action required

1. OTLP panic with empty sources 🐞 Bug ☼ Reliability
Description
ValidateAudit now accepts empty/nil Sources, but Inputs.InputSources returns an empty list for audit
when Sources is omitted/empty, and the LokiStack OTEL migration passes that list to otlp.New.
otlp.New panics when the provided otlpLogSourcesOption is empty, crashing config generation for
audit inputs relying on the new "all sources" default.
Code

internal/validations/observability/inputs/audit.go[R21-23]

	return []metav1.Condition{
		internalobs.NewConditionFromPrefix(obs.ConditionTypeValidInputPrefix, spec.Name, true, obs.ReasonValidationSuccess, fmt.Sprintf("input %q is valid", spec.Name)),
	}
Relevance

⭐⭐⭐ High

Team has merged multiple fixes for generator crashes/invalid configs; likely accept guarding empty
OTLP sources to avoid panic.

PR-#3305
PR-#3182
PR-#3143

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
With the removed audit-source length check, an audit input can validly have sources: []/nil;
however, Inputs.InputSources() returns an empty list for such an audit input, and the LokiStack
OTEL migration forwards that empty list into otlp.New() via otlpLogSourcesOption. otlp.New()
explicitly panics when the option list length is 0, so config generation can crash under a now-valid
configuration.

internal/validations/observability/inputs/audit.go[11-23]
internal/api/observability/input_types.go[84-100]
internal/generator/vector/output/lokistack/lokistack.go[106-127]
internal/generator/vector/output/otlp/otlp.go[55-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Allowing empty/nil audit `sources` (meaning "all sources") now permits configurations where `observability.Inputs(...).InputSources(obs.InputTypeAudit)` returns an empty slice, which is then passed into the LokiStack OpenTelemetry migration path as `otlpLogSourcesOption`. The OTLP generator panics when that option is empty.

### Issue Context
- `ValidateAudit` no longer rejects empty sources, so empty/nil becomes a supported state.
- `Inputs.InputSources()` currently just stringifies `i.Audit.Sources` and does not default empty -> all.
- LokiStack OTEL migration sets `op[otlp.OtlpLogSourcesOption]` to that value.
- `otlp.New()` panics if `otlpLogSourcesOption` is an empty list.

### Fix
Make the “empty/nil sources means all sources” semantic true in the code that computes sources for OTLP migration. Two acceptable approaches:
1) **Preferred (central fix):** Update `internal/api/observability/Inputs.InputSources()` so that:
  - for `InputTypeAudit`: if `i.Audit == nil` or `len(i.Audit.Sources)==0`, insert **all** audit sources (`obs.AuditSources`) instead of inserting none.
  - (optionally) similarly default infra empty -> all infra sources for consistency.
2) **Minimal fix:** Update `getInputSources()` in the LokiStack OTEL migration to add an audit fallback (mirroring the infra fallback) when `len(inputSources)==0 && inputType==obs.InputTypeAudit`.

Also add/adjust a unit test covering LokiStack OTEL datamodel + audit input with `sources: []` (or omitted) to prevent regression.

### Fix Focus Areas
- internal/api/observability/input_types.go[84-100]
- internal/generator/vector/output/lokistack/lokistack.go[117-127]
- internal/generator/vector/output/otlp/otlp.go[55-60]
- internal/generator/vector/output/lokistack/lokistack_test.go[81-100]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines 21 to 23
return []metav1.Condition{
internalobs.NewConditionFromPrefix(obs.ConditionTypeValidInputPrefix, spec.Name, true, obs.ReasonValidationSuccess, fmt.Sprintf("input %q is valid", spec.Name)),
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Otlp panic with empty sources 🐞 Bug ☼ Reliability

ValidateAudit now accepts empty/nil Sources, but Inputs.InputSources returns an empty list for audit
when Sources is omitted/empty, and the LokiStack OTEL migration passes that list to otlp.New.
otlp.New panics when the provided otlpLogSourcesOption is empty, crashing config generation for
audit inputs relying on the new "all sources" default.
Agent Prompt
### Issue description
Allowing empty/nil audit `sources` (meaning "all sources") now permits configurations where `observability.Inputs(...).InputSources(obs.InputTypeAudit)` returns an empty slice, which is then passed into the LokiStack OpenTelemetry migration path as `otlpLogSourcesOption`. The OTLP generator panics when that option is empty.

### Issue Context
- `ValidateAudit` no longer rejects empty sources, so empty/nil becomes a supported state.
- `Inputs.InputSources()` currently just stringifies `i.Audit.Sources` and does not default empty -> all.
- LokiStack OTEL migration sets `op[otlp.OtlpLogSourcesOption]` to that value.
- `otlp.New()` panics if `otlpLogSourcesOption` is an empty list.

### Fix
Make the “empty/nil sources means all sources” semantic true in the code that computes sources for OTLP migration. Two acceptable approaches:
1) **Preferred (central fix):** Update `internal/api/observability/Inputs.InputSources()` so that:
   - for `InputTypeAudit`: if `i.Audit == nil` or `len(i.Audit.Sources)==0`, insert **all** audit sources (`obs.AuditSources`) instead of inserting none.
   - (optionally) similarly default infra empty -> all infra sources for consistency.
2) **Minimal fix:** Update `getInputSources()` in the LokiStack OTEL migration to add an audit fallback (mirroring the infra fallback) when `len(inputSources)==0 && inputType==obs.InputTypeAudit`.

Also add/adjust a unit test covering LokiStack OTEL datamodel + audit input with `sources: []` (or omitted) to prevent regression.

### Fix Focus Areas
- internal/api/observability/input_types.go[84-100]
- internal/generator/vector/output/lokistack/lokistack.go[117-127]
- internal/generator/vector/output/otlp/otlp.go[55-60]
- internal/generator/vector/output/lokistack/lokistack_test.go[81-100]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense

@openshift-ci

openshift-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Clee2691
Once this PR has been reviewed and has the lgtm label, please ask for approval from jcantrill. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
internal/generator/vector/output/lokistack/lokistack_test.go (1)

156-178: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider deduplicating the new test entry against initOptions().

This entry duplicates nearly all of initOptions() (Lines 82-101) solely to change the audit input's Sources to empty. Extracting a shared builder (e.g., a parameterized initOptions(auditSources []obs.AuditSource) or a small helper reused by both) would reduce duplication and ease future maintenance as more edge-case entries are added.

♻️ Example refactor sketch
-		initOptions = func() utils.Options {
+		buildOptions = func(auditSources []obs.AuditSource) utils.Options {
 			output := initOutput()
 			return utils.Options{
 				framework.OptionServiceAccountTokenSecretName: saTokenSecretName,
 				helpers.CLFSpec: observability.ClusterLogForwarderSpec(obs.ClusterLogForwarderSpec{
 					Outputs: []obs.OutputSpec{output},
 					Pipelines: []obs.PipelineSpec{
 						{
 							Name:       "lokistack",
 							InputRefs:  []string{obs.InputTypeApplication.String(), obs.InputTypeInfrastructure.String(), obs.InputTypeAudit.String()},
 							OutputRefs: []string{output.Name},
 						},
 					},
 					Inputs: []obs.InputSpec{
 						{Name: obs.InputTypeApplication.String(), Type: obs.InputTypeApplication},
 						{Name: obs.InputTypeInfrastructure.String(), Type: obs.InputTypeInfrastructure, Infrastructure: &obs.Infrastructure{Sources: obs.InfrastructureSources}},
-						{Name: obs.InputTypeAudit.String(), Type: obs.InputTypeAudit, Audit: &obs.Audit{Sources: obs.AuditSources}},
+						{Name: obs.InputTypeAudit.String(), Type: obs.InputTypeAudit, Audit: &obs.Audit{Sources: auditSources}},
 					},
 				}),
 			}
 		}
+		initOptions = func() utils.Options { return buildOptions(obs.AuditSources) }

Then the new entry becomes: buildOptions(nil).

🤖 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 `@internal/generator/vector/output/lokistack/lokistack_test.go` around lines
156 - 178, The new lokistack test case duplicates almost all of initOptions()
and only differs by using an empty Audit Sources value. Refactor the option
construction in lokistack_test.go by extracting a shared builder, such as a
parameterized initOptions(auditSources []obs.AuditSource) or similar helper, and
reuse it for both the existing initOptions() path and the new "with Otel
datamodel and empty audit sources" entry.
internal/api/observability/input_types.go (1)

86-109: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reserved-default fallback logic looks correct.

The conditional insertion mirrors the pre-existing ReservedApplicationSources pattern and correctly falls back to reserved sets only when the section is nil or Sources is empty. Confirmed consistent with the Infrastructure/Audit CRD doc comments stating omission means "collect all sources."

Minor optional note: the Infrastructure and Audit branches (Lines 93-104) are structurally identical (nil/empty check → reserved fallback vs. derived sources). Could be extracted into a small generic helper, but the duplication is minimal (2 branches) and doesn't currently hurt readability.

🤖 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 `@internal/api/observability/input_types.go` around lines 86 - 109, No
functional bug needs fixing in InputSources; the reserved-default fallback
behavior for obs.InputTypeInfrastructure and obs.InputTypeAudit is already
correct. If you want to address the review’s optional cleanup, factor the
repeated nil/empty Sources fallback logic in Inputs.InputSources into a small
helper used by the Infrastructure and Audit branches, while preserving the
current reserved-set behavior and the existing Application path.
🤖 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.

Nitpick comments:
In `@internal/api/observability/input_types.go`:
- Around line 86-109: No functional bug needs fixing in InputSources; the
reserved-default fallback behavior for obs.InputTypeInfrastructure and
obs.InputTypeAudit is already correct. If you want to address the review’s
optional cleanup, factor the repeated nil/empty Sources fallback logic in
Inputs.InputSources into a small helper used by the Infrastructure and Audit
branches, while preserving the current reserved-set behavior and the existing
Application path.

In `@internal/generator/vector/output/lokistack/lokistack_test.go`:
- Around line 156-178: The new lokistack test case duplicates almost all of
initOptions() and only differs by using an empty Audit Sources value. Refactor
the option construction in lokistack_test.go by extracting a shared builder,
such as a parameterized initOptions(auditSources []obs.AuditSource) or similar
helper, and reuse it for both the existing initOptions() path and the new "with
Otel datamodel and empty audit sources" entry.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ea27578d-1453-4904-b0be-321508013d95

📥 Commits

Reviewing files that changed from the base of the PR and between c02ef14 and e7e47fb.

📒 Files selected for processing (8)
  • internal/api/observability/input_types.go
  • internal/api/observability/input_types_test.go
  • internal/generator/vector/output/lokistack/lokistack.go
  • internal/generator/vector/output/lokistack/lokistack_test.go
  • internal/validations/observability/inputs/audit.go
  • internal/validations/observability/inputs/audit_test.go
  • internal/validations/observability/inputs/infrastructure.go
  • internal/validations/observability/inputs/infrastructure_test.go
💤 Files with no reviewable changes (2)
  • internal/generator/vector/output/lokistack/lokistack.go
  • internal/validations/observability/inputs/audit.go

@Clee2691

Clee2691 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@openshift-ci

openshift-ci Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@Clee2691: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-using-bundle e7e47fb link false /test e2e-using-bundle

Full PR test history. Your PR dashboard.

Details

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 kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants