Skip to content

feat: strip hidden labels from exporter display output#892

Open
bennyz wants to merge 1 commit into
jumpstarter-dev:mainfrom
bennyz:hidden-labels
Open

feat: strip hidden labels from exporter display output#892
bennyz wants to merge 1 commit into
jumpstarter-dev:mainfrom
bennyz:hidden-labels

Conversation

@bennyz

@bennyz bennyz commented Jul 16, 2026

Copy link
Copy Markdown
Member

Labels prefixed with hidden.jumpstarter.dev/ are excluded from jmp get exporters. Pass --show-hidden
to reveal them. Filtering happens at the data boundary in list_exporters() so all display paths get consistent behavior.

This is useful when there is data we need but don't want to pollute the label output too much

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4cc79b4f-f5fa-4bb1-b47b-af3958d016e3

📥 Commits

Reviewing files that changed from the base of the PR and between 94e3423 and 825e5af.

⛔ Files ignored due to path filters (2)
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.gw.go is excluded by !**/*.pb.gw.go
📒 Files selected for processing (23)
  • controller/buf.gen.yaml
  • controller/cmd/main.go
  • controller/deploy/operator/api/v1alpha1/jumpstarter_types.go
  • controller/deploy/operator/api/v1alpha1/zz_generated.deepcopy.go
  • controller/deploy/operator/config/crd/bases/operator.jumpstarter.dev_jumpstarters.yaml
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
  • controller/deploy/operator/test/e2e/e2e_test.go
  • controller/internal/config/config.go
  • controller/internal/config/types.go
  • controller/internal/config/types_test.go
  • controller/internal/service/client/v1/client_service.go
  • controller/internal/service/client/v1/client_service_test.go
  • controller/internal/service/controller_service.go
  • protocol/proto/jumpstarter/client/v1/client.proto
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py
🚧 Files skipped from review as they are similar to previous changes (21)
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • controller/deploy/operator/config/crd/bases/operator.jumpstarter.dev_jumpstarters.yaml
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py
  • controller/buf.gen.yaml
  • protocol/proto/jumpstarter/client/v1/client.proto
  • controller/internal/config/types.go
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py
  • controller/cmd/main.go
  • controller/internal/service/client/v1/client_service_test.go
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
  • controller/deploy/operator/api/v1alpha1/jumpstarter_types.go
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi
  • controller/internal/config/types_test.go
  • controller/deploy/operator/api/v1alpha1/zz_generated.deepcopy.go
  • controller/internal/config/config.go
  • controller/internal/service/client/v1/client_service.go
  • python/packages/jumpstarter/jumpstarter/client/grpc.py

📝 Walkthrough

Walkthrough

Exporter label keys can now be hidden through controller configuration and optionally returned with show_hidden. The option propagates through protobuf, Go services, Python clients, CLI, and MCP interfaces, with shared exporter rendering and tests covering filtering and forwarding.

Changes

Hidden exporter label visibility

Layer / File(s) Summary
Hidden-label configuration wiring
controller/deploy/operator/..., controller/internal/config/..., controller/internal/service/..., controller/cmd/main.go, controller/buf.gen.yaml
Adds hiddenLabels.keys configuration, loads it into controller services, propagates it to the client service, and updates the generated Go package prefix.
Exporter visibility protocol contract
protocol/proto/..., python/packages/jumpstarter-protocol/...
Adds optional show_hidden fields to exporter retrieval and listing requests and regenerates Python protobuf declarations.
Runtime label filtering
controller/internal/service/client/v1/...
Filters configured label keys from GetExporter and ListExporters responses unless show_hidden is enabled, with edge-case tests.
Client and listing propagation
python/packages/jumpstarter/jumpstarter/..., python/packages/jumpstarter-cli/..., python/packages/jumpstarter-mcp/...
Forwards show_hidden through Python client, CLI, and MCP exporter listing flows, with RPC forwarding tests.
Exporter rendering and serialization
python/packages/jumpstarter/jumpstarter/client/grpc.py
Centralizes display options and exporter dumping for table and JSON output.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant ClientConfig
  participant ListExportersRPC
  participant ClientService
  CLI->>ClientConfig: request exporters with show_hidden
  ClientConfig->>ListExportersRPC: send show_hidden
  ListExportersRPC->>ClientService: deliver exporter request
  ClientService-->>ListExportersRPC: filter configured labels unless show_hidden
  ListExportersRPC-->>ClientConfig: return exporter labels
Loading

Possibly related PRs

Suggested labels: enhancement, go, python, protocol

Suggested reviewers: mangelajo, evakhoni

Poem

A rabbit hid labels beneath the moon,
Then showed them with one CLI tune.
Config and services passed them along,
MCP and protobuf joined the song.
Clean exporter lists now hop along.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: hiding exporter labels from display output with an option to reveal them.
Description check ✅ Passed The description matches the changeset by describing hidden-label filtering and the --show-hidden option.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
python/packages/jumpstarter/jumpstarter/client/grpc.py (1)

345-346: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add type hints to _dump_exporter.

For improved developer ergonomics and static analysis, consider adding type annotations for exporter and exclude_fields.

💡 Proposed refactor
-    def _dump_exporter(self, exporter, exclude_fields) -> dict:
+    def _dump_exporter(self, exporter: Exporter, exclude_fields: set[str]) -> dict:
         return exporter.model_dump(mode="json", exclude=exclude_fields)
🤖 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 `@python/packages/jumpstarter/jumpstarter/client/grpc.py` around lines 345 -
346, Add explicit type annotations to the `_dump_exporter` method for both
`exporter` and `exclude_fields`, while retaining its existing `dict` return
annotation. Use the concrete exporter model and exclusion-field types already
established in the surrounding client code or imported definitions.
🤖 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 `@python/packages/jumpstarter/jumpstarter/client/grpc.py`:
- Around line 345-346: Add explicit type annotations to the `_dump_exporter`
method for both `exporter` and `exclude_fields`, while retaining its existing
`dict` return annotation. Use the concrete exporter model and exclusion-field
types already established in the surrounding client code or imported
definitions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e67ed262-0555-41be-ad3a-19daee17cad1

📥 Commits

Reviewing files that changed from the base of the PR and between 2351e86 and afdb0bb.

📒 Files selected for processing (6)
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py

@bennyz

bennyz commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@mangelajo i am not set on the prefix, we could also use _ or something

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py (1)

224-231: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the explicit show_hidden=True path.

This test only verifies the default/hidden-label-filtering path. Add a second case or parameterize the test with show_hidden=True; otherwise a regression that always forwards False would still pass.

🤖 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 `@python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py` around lines 224
- 231, Extend the test around get_exporters.callback.__wrapped__.__wrapped__ to
cover show_hidden=True, either by adding a separate case or parameterizing the
existing case. Assert that config.list_exporters receives show_hidden=True for
that invocation, while preserving the existing default-path assertion.
python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py (1)

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

Keep the hidden-label prefix single-sourced.

The docstring duplicates hidden.jumpstarter.dev/, while filtering uses the shared prefix constant. Since the prefix is not finalized, a future change could make the MCP documentation incorrect. Reuse a shared constant or centralize the user-facing description.

🤖 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 `@python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py` at line 191,
Update the documentation for the show_hidden option near the server argument
definition to derive or reuse the existing shared hidden-label prefix constant
instead of hardcoding hidden.jumpstarter.dev/. Keep the user-facing description
accurate if that constant changes, without duplicating the prefix.
🤖 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 `@python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py`:
- Around line 224-231: Extend the test around
get_exporters.callback.__wrapped__.__wrapped__ to cover show_hidden=True, either
by adding a separate case or parameterizing the existing case. Assert that
config.list_exporters receives show_hidden=True for that invocation, while
preserving the existing default-path assertion.

In `@python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py`:
- Line 191: Update the documentation for the show_hidden option near the server
argument definition to derive or reuse the existing shared hidden-label prefix
constant instead of hardcoding hidden.jumpstarter.dev/. Keep the user-facing
description accurate if that constant changes, without duplicating the prefix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3ed1c3e9-3125-4c1a-a884-10e9b60a3243

📥 Commits

Reviewing files that changed from the base of the PR and between afdb0bb and 0ffdf19.

📒 Files selected for processing (7)
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/client/grpc.py

@mangelajo

mangelajo commented Jul 17, 2026

Copy link
Copy Markdown
Member

@mangelajo i am not set on the prefix, we could also use _ or something

"_" would be invalid for k8s I believe

I was thinking, what if we added an annotation to exporters to list hidden labels, would be very helpful to deprecate labels. May be even later a deprecated annotation to warn users when they are using a phased out label. i.e.

annotations:
jumpstarter.dev/hidden-labels=abc,def,ghi
jumpstarter.dev/deprecated-labels=cde,efg,hij

(but the deprecated is another feature tb...)

Or a better option could be (and that could make more sense) to provide a list in the controller config + operator:

labels:
hiden:
- abc
- def
- ghi
deprecated:
- cde
- efg
- hij

WDYT?

I know you're trying to avoid controller update in this case, but we can backport this and bring it to the lab quickly

@bennyz

bennyz commented Jul 19, 2026

Copy link
Copy Markdown
Member Author

@mangelajo i am not set on the prefix, we could also use _ or something

"_" would be invalid for k8s I believe

it is legal https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set

I was thinking, what if we added an annotation to exporters to list hidden labels, would be very helpful to deprecate labels. May be even later a deprecated annotation to warn users when they are using a phased out label. i.e.

annotations: jumpstarter.dev/hidden-labels=abc,def,ghi jumpstarter.dev/deprecated-labels=cde,efg,hij

(but the deprecated is another feature tb...)

Or a better option could be (and that could make more sense) to provide a list in the controller config + operator:

labels: hiden: - abc - def - ghi deprecated: - cde - efg - hij

WDYT?

I know you're trying to avoid controller update in this case, but we can backport this and bring it to the lab quickly

yeah i was trying to avoid controller changes for something like this, i'll have a look

@coderabbitai coderabbitai Bot left a comment

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.

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 `@controller/deploy/operator/api/v1alpha1/jumpstarter_types.go`:
- Around line 187-190: Move the HiddenLabels field and its associated comments
from the top-level specification into ControllerConfig, preserving its JSON
name, optional behavior, and HiddenLabelsConfig type. Update any references to
read the setting through ControllerConfig while leaving global settings such as
BaseDomain and Authentication unchanged.

In `@python/packages/jumpstarter/jumpstarter/client/grpc.py`:
- Around line 339-341: The _dump_exporter helper hardcodes JSON serialization,
causing model_dump to lose native Python types. In
python/packages/jumpstarter/jumpstarter/client/grpc.py lines 339-341, update
_dump_exporter to accept and forward **kwargs to exporter.model_dump; in lines
357-357, pass mode="json" explicitly at the model_dump_json call site so JSON
output remains serializable.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e15a8ae9-c0ac-450a-9b29-1bc512668776

📥 Commits

Reviewing files that changed from the base of the PR and between 0ffdf19 and 94e3423.

⛔ Files ignored due to path filters (2)
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.gw.go is excluded by !**/*.pb.gw.go
📒 Files selected for processing (22)
  • controller/buf.gen.yaml
  • controller/cmd/main.go
  • controller/deploy/operator/api/v1alpha1/jumpstarter_types.go
  • controller/deploy/operator/api/v1alpha1/zz_generated.deepcopy.go
  • controller/deploy/operator/config/crd/bases/operator.jumpstarter.dev_jumpstarters.yaml
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
  • controller/internal/config/config.go
  • controller/internal/config/types.go
  • controller/internal/config/types_test.go
  • controller/internal/service/client/v1/client_service.go
  • controller/internal/service/client/v1/client_service_test.go
  • controller/internal/service/controller_service.go
  • protocol/proto/jumpstarter/client/v1/client.proto
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get_test.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • python/packages/jumpstarter/jumpstarter/config/client.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py
  • python/packages/jumpstarter-mcp/jumpstarter_mcp/server.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py

Comment on lines +187 to +190
// Hidden labels configuration for hiding specific label keys from exporter listings.
// +optional
HiddenLabels HiddenLabelsConfig `json:"hiddenLabels,omitempty"`
}

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Move HiddenLabels into ControllerConfig.

As per coding guidelines: "Place controller-specific settings (image, replicas, grpc endpoints) within a controller-level configuration, not at the top-level spec".

HiddenLabels governs how the controller filters gRPC API responses, making it a controller-specific setting rather than a global one like BaseDomain or Authentication. Please move it into ControllerConfig.

🤖 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 `@controller/deploy/operator/api/v1alpha1/jumpstarter_types.go` around lines
187 - 190, Move the HiddenLabels field and its associated comments from the
top-level specification into ControllerConfig, preserving its JSON name,
optional behavior, and HiddenLabelsConfig type. Update any references to read
the setting through ControllerConfig while leaving global settings such as
BaseDomain and Authentication unchanged.

Source: Coding guidelines

Comment thread python/packages/jumpstarter/jumpstarter/client/grpc.py Outdated
Add hiddenLabels.keys to the controller ConfigMap and operator CRD.
The server strips matching label keys from ListExporters/GetExporter
responses. Clients pass show_hidden in the proto request to bypass
filtering (jmp get exporters --show-hidden).

This is useful when there is data we need but don't want to pollute
the label output too much

Signed-off-by: Benny Zlotnik <bzlotnik@redhat.com>
Assisted-by: claude-opus-4.6
(google.api.resource_reference) = {type: "jumpstarter.dev/Exporter"}
];
// When true, include labels hidden by controller configuration.
bool show_hidden = 2 [(google.api.field_behavior) = OPTIONAL];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
bool show_hidden = 2 [(google.api.field_behavior) = OPTIONAL];
bool show_hidden_labels = 2 [(google.api.field_behavior) = OPTIONAL];

Otherwise could be mistaken by show hidden "exporters" which would be my first understanding outside of the context of this pr.

// Filter expression for the results.
string filter = 4 [(google.api.field_behavior) = OPTIONAL];
// When true, include labels hidden by controller configuration.
bool show_hidden = 5 [(google.api.field_behavior) = OPTIONAL];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
bool show_hidden = 5 [(google.api.field_behavior) = OPTIONAL];
bool show_hidden_labels = 5 [(google.api.field_behavior) = OPTIONAL];

help="Include disabled exporters in the listing",
)
@click.option(
"--show-hidden",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

for the same reasons:

Suggested change
"--show-hidden",
"--show-hidden-labels",

it's also a parameter that wouldn't be used so often, so it's ok to make it a little bit longer IMO.

@handle_exceptions_with_reauthentication(relogin_client)
def get_exporters(config, selector: str | None, output: OutputType, with_options: list[str], allow_disabled: bool):
def get_exporters(
config, selector: str | None, output: OutputType, with_options: list[str], allow_disabled: bool, show_hidden: bool

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
config, selector: str | None, output: OutputType, with_options: list[str], allow_disabled: bool, show_hidden: bool
config, selector: str | None, output: OutputType, with_options: list[str], allow_disabled: bool, show_hidden_labels: bool

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.

2 participants