Skip to content

OSAC-2164: ClusterVersion CLI and ResolveFieldPath reuse - #181

Merged
omer-vishlitzky merged 3 commits into
osac-project:mainfrom
sk-ilya:clusterversion-cli
Aug 10, 2026
Merged

OSAC-2164: ClusterVersion CLI and ResolveFieldPath reuse#181
omer-vishlitzky merged 3 commits into
osac-project:mainfrom
sk-ilya:clusterversion-cli

Conversation

@sk-ilya

@sk-ilya sk-ilya commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
  • Add ClusterVersion support to the CLI: VERSION column in cluster list tables with lookup_field-based resolution, and a nested Version section in describe cluster output
  • Reuse generic ResolveFieldPath[T] across four hand-rolled proto field walkers in auth, references, and reflection packages

Assisted-by: Claude noreply@anthropic.com

Summary by CodeRabbit

  • New Features
    • Added a VERSION column to cluster tables, displaying the associated version name.
    • Cluster details now show version, status, deprecation, and obsolescence information when available.
  • Bug Fixes
    • Cluster details continue rendering when version information cannot be retrieved, with a warning instead of failing.
    • Version display falls back gracefully when data or names are unavailable.
  • Improvements
    • Enhanced table lookups for displaying related resource values more reliably.

@openshift-ci-robot

openshift-ci-robot commented Aug 6, 2026

Copy link
Copy Markdown

@sk-ilya: This pull request references OSAC-2164 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 story to target the "5.0.0" version, but no target version was set.

This pull request references OSAC-2158 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 story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

  • Add ClusterVersion support to the CLI: VERSION column in cluster list tables with lookup_field-based resolution, and a nested Version section in describe cluster output
  • Reuse generic ResolveFieldPath[T] across four hand-rolled proto field walkers in auth, references, and reflection packages

Assisted-by: Claude noreply@anthropic.com

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.

@sk-ilya
sk-ilya force-pushed the clusterversion-cli branch from ada1b1c to 9c82791 Compare August 6, 2026 12:23
@sk-ilya
sk-ilya force-pushed the clusterversion-cli branch from 9c82791 to d21e9b0 Compare August 6, 2026 12:24
@sk-ilya sk-ilya changed the title OSAC-2164, OSAC-2158: ClusterVersion CLI and ResolveFieldPath reuse OSAC-2164: ClusterVersion CLI and ResolveFieldPath reuse Aug 6, 2026
@sk-ilya
sk-ilya requested review from jhernand and tzvatot August 6, 2026 12:26
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The PR adds generic protobuf field-path reflection helpers and migrates metadata extraction to them. It adds ClusterVersion lookup and lifecycle details to cluster descriptions and table rendering.

Changes

Cluster version and reflection updates

Layer / File(s) Summary
Protobuf field-path resolution
fulfillment-service/internal/reflection/reflection_field_path.go, fulfillment-service/internal/reflection/*_test.go
Adds dotted-field resolution with type validation and fallback handling. Updates tenant helper tests to use local context helpers.
Metadata and reference resolution
fulfillment-service/internal/auth/grpc_authz_interceptor.go, fulfillment-service/internal/references/*
Uses field-path helpers to resolve project, tenant, and metadata values with empty-string fallbacks.
Table reference rendering
fulfillment-service/internal/rendering/table_renderer.go, fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go, fulfillment-service/internal/rendering/tables/*
Adds typed protobuf and CEL lookup resolution, caches lookup objects, adds VERSION columns, and removes legacy lookup flags.
Cluster description version details
fulfillment-service/internal/cmd/cli/describe/cluster/*
Looks up referenced ClusterVersion objects and renders version, state, deprecation, and obsolescence details. Lookup failures produce warnings and continue rendering.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ClusterDescribe
  participant ClusterVersionsClient
  participant ClusterRenderer
  ClusterDescribe->>ClusterVersionsClient: Resolve referenced ClusterVersion
  ClusterVersionsClient-->>ClusterDescribe: Return version or lookup error
  ClusterDescribe->>ClusterRenderer: Render cluster with optional version details
Loading

Possibly related PRs

Suggested reviewers: tzvatot, vladikr, akshaynadkarni

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the two main changes: ClusterVersion CLI support and reuse of ResolveFieldPath.
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.
No-Hardcoded-Secrets ✅ Passed The cumulative PR diff contains no credential assignments, API/token formats, embedded-credential URLs, private-key material, or base64/hex blobs over 32 characters.
No-Weak-Crypto ✅ Passed The PR changes add protobuf reflection, CEL lookup, and CLI rendering only; scans of all added lines and affected files found no MD5, SHA1, DES, RC4, Blowfish, ECB, or secret comparisons.
No-Injection-Vectors ✅ Passed Changed code has no SQL, shell, pickle, unsafe YAML, or HTML injection APIs; CEL/OPA evaluation uses static expressions, and lookup keys are quoted with %q.
Container-Privileges ✅ Passed The PR diff adds no container/Kubernetes privilege settings; changed YAML files are table definitions, and no added line contains privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivi...
No-Sensitive-Data-In-Logs ✅ Passed New logging records a ClusterVersion name, type/key metadata, and lookup errors; no passwords, tokens, API keys, PII, session IDs, hostnames, or customer payloads are logged.
Ai-Attribution ✅ Passed AI use is disclosed, and all three PR commits include an Assisted-by: Claude trailer; none includes an AI Co-Authored-By trailer.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go (1)

114-165: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Propagate output errors from renderCluster.

Return an error from renderCluster and propagate all fmt write errors and both tabwriter.Flush() errors to run. Otherwise, the command can return success after a failed output write.

🤖 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 `@fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go`
around lines 114 - 165, Change renderCluster to return an error, check and
propagate every fmt write result and both tabwriter.Flush calls, including
versionWriter.Flush. Update run to receive and return the renderCluster error so
failed output writes cause the command to fail.

Sources: Path instructions, Learnings

🤖 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 `@fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go`:
- Around line 91-100: Update the ClusterVersions request inside the lookup
callback passed to lookup.Find to explicitly include every supported version
state, including OBSOLETE, and add a lookup-level test covering an obsolete
referenced version. In renderCluster, return errors from both
tabwriter.Writer.Flush calls and propagate those errors to the caller.

---

Outside diff comments:
In `@fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go`:
- Around line 114-165: Change renderCluster to return an error, check and
propagate every fmt write result and both tabwriter.Flush calls, including
versionWriter.Flush. Update run to receive and return the renderCluster error so
failed output writes cause the command to fail.
🪄 Autofix

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: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aff66810-c913-4913-a030-7d6ac9e014ce

📥 Commits

Reviewing files that changed from the base of the PR and between cab5b6c and d21e9b0.

📒 Files selected for processing (13)
  • fulfillment-service/internal/auth/grpc_authz_interceptor.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster_test.go
  • fulfillment-service/internal/references/lookups.go
  • fulfillment-service/internal/references/reference_validator.go
  • fulfillment-service/internal/reflection/reflection_field_path.go
  • fulfillment-service/internal/reflection/reflection_field_path_test.go
  • fulfillment-service/internal/reflection/reflection_helper.go
  • fulfillment-service/internal/reflection/reflection_helper_test.go
  • fulfillment-service/internal/rendering/table_renderer.go
  • fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Cluster.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Cluster.yaml

@sk-ilya
sk-ilya requested a review from vladikr August 6, 2026 14:04
@sk-ilya
sk-ilya force-pushed the clusterversion-cli branch from d21e9b0 to f1695d7 Compare August 6, 2026 14:37
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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.

Actionable comments posted: 2

🤖 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
`@fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go`:
- Around line 77-88: Update the Lookup mock in the table renderer test to
explicitly return versionHelper only for the ClusterVersion descriptor, while
retaining clusterHelper for the cluster descriptor. Replace the default fallback
with a test failure for any unexpected object type so invalid lookups cannot
pass.
- Around line 137-145: Update the test case around renderClusters to use a
cluster ID without a hyphen, then assert the VERSION column specifically
contains “-” rather than matching any hyphen in the rendered row. Keep the
no-version_name setup and makeVersionHelper(nil) behavior unchanged.
🪄 Autofix

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: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5fa7f139-3960-41d1-9ba9-ab3af2c88be5

📥 Commits

Reviewing files that changed from the base of the PR and between bd212f3 and f1695d7.

📒 Files selected for processing (13)
  • fulfillment-service/internal/auth/grpc_authz_interceptor.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster_test.go
  • fulfillment-service/internal/references/lookups.go
  • fulfillment-service/internal/references/reference_validator.go
  • fulfillment-service/internal/reflection/reflection_field_path.go
  • fulfillment-service/internal/reflection/reflection_field_path_test.go
  • fulfillment-service/internal/reflection/reflection_helper.go
  • fulfillment-service/internal/reflection/reflection_helper_test.go
  • fulfillment-service/internal/rendering/table_renderer.go
  • fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Cluster.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Cluster.yaml
🚧 Files skipped from review as they are similar to previous changes (12)
  • fulfillment-service/internal/reflection/reflection_helper.go
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Cluster.yaml
  • fulfillment-service/internal/auth/grpc_authz_interceptor.go
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Cluster.yaml
  • fulfillment-service/internal/references/lookups.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster.go
  • fulfillment-service/internal/rendering/table_renderer.go
  • fulfillment-service/internal/cmd/cli/describe/cluster/describe_cluster_test.go
  • fulfillment-service/internal/references/reference_validator.go
  • fulfillment-service/internal/reflection/reflection_field_path.go
  • fulfillment-service/internal/reflection/reflection_field_path_test.go
  • fulfillment-service/internal/reflection/reflection_helper_test.go

Comment thread fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go Outdated

@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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go (1)

130-131: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

The negative assertion on line 131 can never fail.

The renderer writes through a tabwriter.Writer that is configured with ' ' as the pad character. Flush replaces the tab separators with spaces, so the rendered output contains no \t. ContainSubstring("4-17-0\t") therefore always passes and proves nothing about the VERSION cell.

Assert the cell content directly, in the same way as the '-' test on lines 141-145.

💚 Proposed assertion
 		output := renderClusters(ctx, cluster, makeVersionHelper([]proto.Message{version}))
-		Expect(output).To(ContainSubstring("4.17.0"))
-		Expect(output).ToNot(ContainSubstring("4-17-0\t"))
+		lines := strings.Split(strings.TrimSpace(output), "\n")
+		Expect(lines).To(HaveLen(2))
+		versionCol := strings.Index(lines[0], "VERSION")
+		Expect(versionCol).To(BeNumerically(">=", 0))
+		Expect(strings.Fields(lines[1][versionCol:])[0]).To(Equal("4.17.0"))
🤖 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
`@fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go`
around lines 130 - 131, Replace the ineffective tab-based negative assertion in
the table renderer test with a direct assertion on the VERSION cell, matching
the existing '-' test pattern around the relevant cell content. Verify that the
rendered VERSION value is “4.17.0” and not the hyphenated form, without relying
on tab separators after tabwriter flushes.
🧹 Nitpick comments (2)
fulfillment-service/internal/rendering/table_renderer.go (1)

523-524: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

The registries map is unsynchronized shared state in a CEL binding.

lookupFunction captures registries and mutates it inside the overload binding. Today renderRow runs sequentially, so this is safe. cel.Program values are otherwise safe for concurrent evaluation, so the shared map is a trap for a future parallel render. Add a short comment that the renderer is single-goroutine, or guard the map with a mutex.

Also applies to: 553-572

🤖 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 `@fulfillment-service/internal/rendering/table_renderer.go` around lines 523 -
524, Add synchronization for the shared registries map captured by
TableRenderer.lookupFunction, protecting mutations in the overload binding with
a mutex so concurrent CEL evaluations remain safe. Use the existing
lookupFunction closure and its registry-update path; do not change the lookup
behavior.
fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go (1)

166-175: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

This test rebuilds the mock helper wiring instead of reusing renderClusters.

The setup on lines 166-182 duplicates the builder block on lines 103-113, and its Lookup stub silently returns nil for unexpected types while the shared stub calls Fail. Extract the renderer construction into a small helper so both tests share one strict Lookup behavior.

🤖 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
`@fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go`
around lines 166 - 175, Extract the renderer construction currently duplicated
around renderClusters and the test setup into a shared test helper. Reuse that
helper in both tests, preserving the strict Lookup behavior that calls Fail for
unexpected object types instead of returning nil.
🤖 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 `@fulfillment-service/internal/rendering/table_renderer.go`:
- Around line 516-586: Update lookupFunction to degrade gracefully when
r.helper.Lookup returns nil or type-registry creation/descriptor registration
fails: log a warning with the target type and error context, then return
registry.NativeToValue(helper.Instance()) instead of types.NewErr. Preserve
normal lookup and key-miss behavior, and ensure the fallback uses the empty
instance for the resolved target type.

---

Outside diff comments:
In
`@fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go`:
- Around line 130-131: Replace the ineffective tab-based negative assertion in
the table renderer test with a direct assertion on the VERSION cell, matching
the existing '-' test pattern around the relevant cell content. Verify that the
rendered VERSION value is “4.17.0” and not the hyphenated form, without relying
on tab separators after tabwriter flushes.

---

Nitpick comments:
In
`@fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go`:
- Around line 166-175: Extract the renderer construction currently duplicated
around renderClusters and the test setup into a shared test helper. Reuse that
helper in both tests, preserving the strict Lookup behavior that calls Fail for
unexpected object types instead of returning nil.

In `@fulfillment-service/internal/rendering/table_renderer.go`:
- Around line 523-524: Add synchronization for the shared registries map
captured by TableRenderer.lookupFunction, protecting mutations in the overload
binding with a mutex so concurrent CEL evaluations remain safe. Use the existing
lookupFunction closure and its registry-update path; do not change the lookup
behavior.
🪄 Autofix

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: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a47e9c17-efba-4c44-917c-c61a02acd82f

📥 Commits

Reviewing files that changed from the base of the PR and between c484e05 and 9ef7777.

📒 Files selected for processing (24)
  • fulfillment-service/internal/rendering/table_renderer.go
  • fulfillment-service/internal/rendering/table_renderer_cluster_version_test.go
  • fulfillment-service/internal/rendering/table_renderer_compute_instance_test.go
  • fulfillment-service/internal/rendering/tables/osac.private.v1.BareMetalInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Cluster.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ComputeInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIP.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIPAttachment.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIPPool.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.NATGateway.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.RoleBinding.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.SecurityGroup.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Subnet.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.User.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.VirtualNetwork.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.BareMetalInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Cluster.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.ComputeInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.NATGateway.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.RoleBinding.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.SecurityGroup.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Subnet.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.User.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.VirtualNetwork.yaml
💤 Files with no reviewable changes (19)
  • fulfillment-service/internal/rendering/tables/osac.public.v1.NATGateway.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.BareMetalInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ComputeInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.SecurityGroup.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.BareMetalInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.User.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.NATGateway.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Subnet.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.RoleBinding.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.RoleBinding.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIPPool.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.ComputeInstance.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIP.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.ExternalIPAttachment.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.User.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.VirtualNetwork.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.SecurityGroup.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.VirtualNetwork.yaml
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Subnet.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • fulfillment-service/internal/rendering/tables/osac.public.v1.Cluster.yaml
  • fulfillment-service/internal/rendering/tables/osac.private.v1.Cluster.yaml

Comment on lines +516 to +586
// lookupFunction returns a CEL environment option that registers the lookup() function. The function
// takes a protobuf reference message (e.g. ClusterVersionReference) and returns the corresponding
// object (e.g. ClusterVersion) so that the CEL expression can navigate its fields.
//
// Each lookup target type gets its own CEL type registry, created lazily on first use and cached
// for the lifetime of the Render call. This avoids eagerly registering every resource type in the
// CEL environment.
func (r *TableRenderer) lookupFunction(ctx context.Context) cel.EnvOption {
registries := map[protoreflect.FullName]*types.Registry{}

return cel.Function("lookup",
cel.Overload(
"lookup_ref",
[]*cel.Type{cel.DynType},
cel.DynType,
cel.UnaryBinding(func(val ref.Val) ref.Val {
msg, ok := val.Value().(proto.Message)
if !ok {
return types.NewErr("lookup: expected a protobuf reference message, got %T", val.Value())
}
targetType, ok := referenceTargetType(msg.ProtoReflect().Descriptor())
if !ok {
r.logger.ErrorContext(
ctx,
"Failed to derive lookup target type from reference message",
slog.String("message", string(msg.ProtoReflect().Descriptor().FullName())),
)
return types.NewErr(
"lookup: cannot derive target type from %q",
msg.ProtoReflect().Descriptor().FullName(),
)
}
helper := r.helper.Lookup(string(targetType))
if helper == nil {
return types.NewErr("lookup: unknown target type %q", targetType)
}

registry, ok := registries[targetType]
if !ok {
var err error
registry, err = types.NewRegistry()
if err != nil {
return types.NewErr(
"lookup: failed to create type registry for %q: %v",
targetType, err,
)
}
for _, fd := range pb.CollectFileDescriptorSet(helper.Instance()) {
if err = registry.RegisterDescriptor(fd); err != nil {
return types.NewErr(
"lookup: failed to register type %q: %v",
targetType, err,
)
}
}
registries[targetType] = registry
}

key := referenceKey(msg)
if key == "" {
return registry.NativeToValue(helper.Instance())
}
object := r.resolveObject(ctx, targetType, key)
if object == nil {
return registry.NativeToValue(helper.Instance())
}
return registry.NativeToValue(object)
}),
),
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

A missing helper or registry failure now aborts the whole table.

lookup() returns types.NewErr for an unknown target type and for registry failures. renderRow propagates the evaluation error, so Render fails and the user sees no rows at all. The rest of the renderer degrades gracefully on purpose: Render falls back to the default table on load failure, and lookupName falls back to the key. Keep that behavior here and return the empty instance instead, with a logged warning.

🛡️ Proposed graceful fallback
 				helper := r.helper.Lookup(string(targetType))
 				if helper == nil {
-					return types.NewErr("lookup: unknown target type %q", targetType)
+					r.logger.WarnContext(
+						ctx,
+						"Failed to find object helper for lookup target type",
+						slog.String("type", string(targetType)),
+					)
+					return types.NewErr("lookup: unknown target type %q", targetType)
 				}

Alternatively, return a dynamic empty message of targetType so the caller expression still evaluates.

🤖 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 `@fulfillment-service/internal/rendering/table_renderer.go` around lines 516 -
586, Update lookupFunction to degrade gracefully when r.helper.Lookup returns
nil or type-registry creation/descriptor registration fails: log a warning with
the target type and error context, then return
registry.NativeToValue(helper.Instance()) instead of types.NewErr. Preserve
normal lookup and key-miss behavior, and ensure the fallback uses the empty
instance for the resolved target type.

@sk-ilya

sk-ilya commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@jhernand I had to rebase, could you please approve once again?

Add VERSION column to cluster list tables (public and private) that
resolves version_name to the semver string via a new lookup_field
option in the table renderer. Extend describe cluster to fetch and
display ClusterVersion details in a nested section. Move the field
path resolver to the reflection package as a reusable utility.

Assisted-by: Claude <noreply@anthropic.com>
… walkers

Replace four manual protobuf field-walking implementations with calls to
the generic ResolveFieldPath[T] / ResolveFieldPathOr[T] helpers in the
reflection package. Break the test-time import cycle by replacing the
config.TenantFromContext dependency in reflection tests with test-local
context helpers.

Assisted-by: Claude <noreply@anthropic.com>
Replace the explicit lookup boolean with auto-detection via the proto
registry, and introduce a lazy per-target CEL type registry for the
lookup() function using pb.CollectFileDescriptorSet for complete
transitive import coverage.

- Remove Lookup bool and LookupField from columnLayout; renderCell now
  auto-detects message types via FindMessageByName (same as enums use
  FindEnumByName)
- Remove lookup: true from all 21 YAML table definitions
- Change VERSION column to use lookup(this.spec.version).spec.version
  CEL expression instead of the old lookup_field mechanism
- Add lookup() CEL function with lazy type registries created per target
  type on first use, avoiding eager registration of all resource types
- Extract resolveObject as shared cache+fetch core for both lookupName
  and lookupFunction
- Add referenceTargetType and referenceKey helpers for the lookup()
  convention
- Add test for cross-file type navigation via lookup()

Assisted-by: Claude <noreply@anthropic.com>
@omer-vishlitzky

Copy link
Copy Markdown
Contributor

/lgtm
/approve

@openshift-ci

openshift-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhernand, omer-vishlitzky, sk-ilya

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

The pull request process is described 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

@omer-vishlitzky
omer-vishlitzky added this pull request to the merge queue Aug 10, 2026
Merged via the queue into osac-project:main with commit e191d8e Aug 10, 2026
35 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants