Skip to content

feat: add enabled field to Exporter CRD and allowDisabled to Lease (JEP-0014 Phase 1)#863

Merged
mangelajo merged 6 commits into
mainfrom
feat/exporter-enabled-field
Jul 8, 2026
Merged

feat: add enabled field to Exporter CRD and allowDisabled to Lease (JEP-0014 Phase 1)#863
mangelajo merged 6 commits into
mainfrom
feat/exporter-enabled-field

Conversation

@mangelajo

@mangelajo mangelajo commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Implements Phase 1 of JEP-0014: Virtual Scalable Exporters — the enabled field on the Exporter CRD.

This is the foundational building block for graceful scale-down of virtual exporter pools and is immediately useful for physical exporter maintenance workflows.

What Changed

Exporter CRD: spec.enabled field

  • New boolean field (default: true) that controls whether the controller will assign new leases to this exporter
  • When false, the exporter is excluded from selector-based lease matching and explicitly rejected for exporterRef-based leases
  • Backward compatible: existing exporters with no enabled field behave as enabled: true
  • New Enabled printer column visible in kubectl get exporters

Lease CRD: spec.allowDisabled field

  • New boolean field that permits leasing a disabled exporter when used with exporterRef
  • Useful for investigating broken exporters that have been administratively disabled
  • If a user targets a disabled exporter without allowDisabled, the lease gets an Unsatisfiable condition with a helpful error message:

    Requested exporter X is disabled. To lease a disabled exporter, set spec.allowDisabled: true on the Lease, or use --allow-disabled with jmp create lease

Controller Logic

  • filterOutDisabledExporters(): filters disabled exporters from selector-based lease matching (before policy checks)
  • ExporterRef path: checks if the targeted exporter is disabled, returns Unsatisfiable("ExporterDisabled") unless allowDisabled is set

Protocol (gRPC)

  • Exporter message: added enabled field (field 6, OUTPUT_ONLY)
  • Lease message: added allow_disabled field (field 14, IMMUTABLE)
  • ToProtobuf() methods updated to serialize both fields
  • buf.gen.yaml updated to use local protocol/proto as source of truth (replaces external git repo reference)

CLI

  • jmp create lease --allow-disabled: new flag to permit leasing disabled exporters
  • jmp get exporters: disabled exporters are hidden by default; use --allow-disabled to show them (adds an ENABLED column)

Use Cases

Lab maintenance

# Admin takes an exporter offline for maintenance
kubectl patch exporter broken-board -p '{"spec":{"enabled":false}}'

# Leases no longer match this exporter
jmp lease -l board=rpi4  # skips the disabled exporter

# Listing hides disabled exporters by default
jmp get exporters         # broken-board not shown
jmp get exporters --allow-disabled  # shows all, with ENABLED column

# Investigator can still access it explicitly
jmp create lease -n broken-board --allow-disabled --duration 1h

Graceful scale-down (JEP-0014)

1. ExporterSet controller sets enabled: false on the target exporter
2. Controller waits to confirm no lease was assigned
3. Controller deletes the Pod and Exporter CR

Tests

Go (controller)

  • Unit test: filterOutDisabledExporters with nil/true/false Enabled values, slice immutability
  • Integration test: disabled exporter via ExporterRefExporterDisabled reason with helpful message
  • Integration test: disabled exporter via ExporterRef + AllowDisabled: true → lease succeeds
  • Integration test: selector match with one disabled exporter → lease goes to enabled one
  • Integration test: selector match with all disabled → unsatisfiable

Python (CLI)

  • Updated create_test.py to pass allow_disabled parameter
  • Updated grpc_test.py display tests — ENABLED column only shown with show_disabled
  • New TestWithDisabledOption tests for conditional ENABLED column

Backward Compatibility

  • spec.enabled defaults to true — existing Exporters behave exactly as before
  • spec.allowDisabled defaults to false — existing Leases behave exactly as before
  • No changes to the existing gRPC protocol for physical exporters (fields are additive)

References

…EP-0014 Phase 1)

Add spec.enabled boolean field to the Exporter CRD (default: true). When set
to false, the jumpstarter-controller will not assign new leases to the
exporter. This is useful for:

- Temporarily taking a physical exporter offline for maintenance
- Graceful scale-down of virtual exporter pools (JEP-0014)
- Investigating broken exporters without interference

Add spec.allowDisabled boolean field to the Lease CRD. When set to true
alongside exporterRef, allows leasing a disabled exporter for investigation
purposes. If a user targets a disabled exporter without allowDisabled, the
lease is marked Unsatisfiable with a helpful error message explaining how
to use --allow-disabled.

Changes:
- Exporter CRD: add spec.enabled field with kubebuilder default=true
- Exporter CRD: add Enabled printer column for kubectl get exporters
- Lease CRD: add spec.allowDisabled field
- Controller: add filterOutDisabledExporters() for selector-based leases
- Controller: check enabled status for ExporterRef-based leases
- Proto: add enabled field to Exporter message (field 6)
- Proto: add allow_disabled field to Lease message (field 14)
- CLI: add --allow-disabled flag to jmp create lease
- CLI: show ENABLED column in jmp get exporters output
- Tests: unit tests for filterOutDisabledExporters
- Tests: integration tests for disabled exporter scenarios

Implements: JEP-0014 Phase 1
Ref: #41
@coderabbitai

coderabbitai Bot commented Jul 7, 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: 42ff9187-cf4b-44df-a048-586d342bc27d

📥 Commits

Reviewing files that changed from the base of the PR and between 002364e and dca9d31.

⛔ Files ignored due to path filters (1)
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (7)
  • controller/api/v1alpha1/exporter_helpers.go
  • controller/internal/controller/lease_controller.go
  • controller/internal/controller/lease_controller_test.go
  • protocol/proto/jumpstarter/client/v1/client.proto
  • 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
✅ Files skipped from review due to trivial changes (1)
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • protocol/proto/jumpstarter/client/v1/client.proto
  • controller/internal/controller/lease_controller.go
  • controller/internal/controller/lease_controller_test.go
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi
  • controller/api/v1alpha1/exporter_helpers.go

📝 Walkthrough

Walkthrough

Adds exporter enabled-state and lease allow-disabled fields across the Go API, CRDs, controller logic, protobuf contracts, and Python client/CLI/config code. Also switches protobuf generation to local proto sources and regenerates protocol stubs and docs.

Changes

Exporter Enabled / Lease Allow-Disabled Feature

Layer / File(s) Summary
Go API and protobuf contracts
controller/api/v1alpha1/exporter_helpers.go, exporter_types.go, lease_helpers.go, lease_types.go, zz_generated.deepcopy.go, protocol/proto/jumpstarter/client/v1/client.proto, python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py, python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi
Adds exporter enabled-state and lease allow-disabled fields, plus helper, deepcopy, protobuf conversion, and generated client descriptor/type updates for those fields.
Lease reconciliation checks
controller/internal/controller/lease_controller.go, controller/internal/controller/lease_controller_test.go
Rejects disabled exporters for explicit exporter references unless allowed, filters disabled exporters from selector-based matching, and adds coverage for both paths.
Python client model and config wiring
python/packages/jumpstarter/jumpstarter/client/grpc.py, grpc_test.py, config/client.py, client_config_test.py
Adds disabled-exporter filtering and serialization behavior to exporter lists, adds exporter enabled-state handling, and forwards allow-disabled through client config with tests.
CLI flags and command plumbing
python/packages/jumpstarter-cli/jumpstarter_cli/create.py, get.py, create_test.py, get_test.py
Adds allow-disabled flags to lease creation and exporter listing commands and updates the related tests.

Protobuf Toolchain Migration and Generated Stub Docstring Refresh

Layer / File(s) Summary
Local proto directory migration
controller/Makefile, controller/buf.gen.yaml, python/Makefile, python/buf.gen.yaml
Updates Makefiles and buf inputs to use the local ../protocol/proto directory.
Client stub regeneration
python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py, client_pb2_grpc.pyi, client_pb2.py, client_pb2.pyi, python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/*
Refreshes generated client protocol and gRPC stubs, including docstrings, class syntax, and descriptor payloads.
Other generated protobuf docs
python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi, router_pb2.pyi, router_pb2_grpc.py, router_pb2_grpc.pyi
Refreshes Kubernetes and router generated stubs with updated docstrings and class syntax.

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

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant ClientConfig
  participant ClientService
  participant LeaseReconciler

  CLI->>ClientConfig: create_lease(allow_disabled)
  ClientConfig->>ClientService: CreateLease(allow_disabled)
  ClientService->>LeaseReconciler: Lease.allow_disabled=true
  LeaseReconciler->>LeaseReconciler: check exporter IsEnabled()
  alt Exporter disabled and not allowed
    LeaseReconciler-->>ClientService: Unsatisfiable(ExporterDisabled)
  else Exporter enabled or allowed
    LeaseReconciler-->>ClientService: lease assignment proceeds
  end
Loading

Possibly related PRs

Suggested labels: enhancement, go, python, protocol

Suggested reviewers: bennyz

Poem

A rabbit hops where enabled flags glow,
Disabled ones wait in the row.
Leases now choose with a cautious new grace,
And buf runs local, quick in place. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding enabled to Exporter and allowDisabled to Lease for JEP-0014 Phase 1.
Description check ✅ Passed The description matches the changeset and accurately describes the Exporter, Lease, controller, protocol, and CLI updates.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/exporter-enabled-field

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.

Comment thread python/packages/jumpstarter/jumpstarter/client/grpc.py Outdated
mangelajo added 4 commits July 7, 2026 19:39
Per review feedback, disabled exporters are now hidden from jmp get
exporters output by default. Use --allow-disabled to include them
(which also adds an ENABLED column to distinguish them).

- ExporterList filters out disabled exporters unless include_disabled=True
- jmp get exporters: add --allow-disabled flag
- ENABLED column only shown when --allow-disabled is used
- WithOptions: add show_disabled field
- Tests: revert unconditional ENABLED column, add TestWithDisabledOption
Update buf.gen.yaml in both controller/ and python/ to use the local
protocol/proto directory instead of the external jumpstarter-protocol
git repo. This makes the monorepo the single source of truth for proto
definitions and removes the need to sync changes to an external repo
before regenerating stubs.

The Makefile protobuf-gen targets now mount the monorepo root into the
container so the ../protocol/proto relative path resolves correctly.
Add missing allow_disabled argument to test calls that invoke
get_exporters and CreateLease after the new parameter was added.
Add tests for _visible_exporters(), rich_add_rows, rich_add_names,
model_dump_json, and model_dump with disabled exporter filtering to
meet the 80% diff coverage requirement.
@mangelajo mangelajo marked this pull request as ready for review July 8, 2026 08:21
@mangelajo mangelajo requested review from evakhoni and kirkbrauer July 8, 2026 08:21

@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

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

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

Consider extracting shared exclude_fields logic.

model_dump_json and model_dump duplicate the same exclude_fields construction and _visible_exporters() iteration. Extracting a helper would reduce maintenance burden when new conditional-exclusion fields are added.

♻️ Proposed helper extraction
+def _build_exporters_data(self):
+    """Build the exporters list with conditional field exclusion."""
+    exclude_fields = set()
+    if not self.include_leases:
+        exclude_fields.add("lease")
+    if not self.include_online:
+        exclude_fields.add("online")
+    if not self.include_status:
+        exclude_fields.add("status")
+    if not self.include_disabled:
+        exclude_fields.add("enabled")
+    return {
+        "exporters": [
+            exporter.model_dump(mode="json", exclude=exclude_fields)
+            for exporter in self._visible_exporters()
+        ]
+    }
+
 def model_dump_json(self, **kwargs):
     json_kwargs = {k: v for k, v in kwargs.items() if k in {"indent", "separators", "sort_keys", "ensure_ascii"}}
-
-    # Determine which fields to exclude
-    exclude_fields = set()
-    if not self.include_leases:
-        exclude_fields.add("lease")
-    if not self.include_online:
-        exclude_fields.add("online")
-    if not self.include_status:
-        exclude_fields.add("status")
-    if not self.include_disabled:
-        exclude_fields.add("enabled")
-
-    data = {
-        "exporters": [
-            exporter.model_dump(mode="json", exclude=exclude_fields)
-            for exporter in self._visible_exporters()
-        ]
-    }
+    data = self._build_exporters_data()
     return json.dumps(data, **json_kwargs)

 def model_dump(self, **kwargs):
-    exclude_fields = set()
-    if not self.include_leases:
-        exclude_fields.add("lease")
-    if not self.include_online:
-        exclude_fields.add("online")
-    if not self.include_status:
-        exclude_fields.add("status")
-    if not self.include_disabled:
-        exclude_fields.add("enabled")
-
-    return {
-        "exporters": [
-            exporter.model_dump(mode="json", exclude=exclude_fields)
-            for exporter in self._visible_exporters()
-        ]
-    }
+    return self._build_exporters_data()
🤖 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 341 -
379, Extract the duplicated exporter serialization logic in grpc.py by
introducing a shared helper around model_dump_json and model_dump, reusing the
same exclude_fields construction and _visible_exporters() iteration in both
methods. Keep the helper centered on the unique symbols model_dump_json,
model_dump, and _visible_exporters so any future include_* field changes only
need to be updated in one place.
🤖 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/internal/controller/lease_controller_test.go`:
- Around line 818-834: The “should be unsatisfiable when all matching exporters
are disabled” test in lease_controller_test.go only checks that
Status.ExporterRef is nil, which can also match a Pending result. Update this
test to assert the lease status condition is explicitly Unsatisfiable, using the
same condition helper/pattern already used in the other lease reconciliation
tests (for example, the assertions around reconcileLease and getLease elsewhere
in this file), so the test verifies both no ExporterRef and the correct terminal
condition.

In `@controller/internal/controller/lease_controller.go`:
- Around line 263-270: The selector-based path in reconcileStatusExporterRef is
conflating “no exporters matched” with “all matching exporters were disabled”
after filterOutDisabledExporters. Add an explicit check right after filtering
list results from ListMatchingExporters so that when listed.Items is non-empty
but matchingExporters becomes empty, you return a disabled-exporter-specific
status/reason instead of falling through to the NoAccess branch. Keep the
existing no-match and policy-no-access handling separate by using the
matchingExporters, listed.Items, and reconcileStatusExporterRef branches to
distinguish the cases.

---

Nitpick comments:
In `@python/packages/jumpstarter/jumpstarter/client/grpc.py`:
- Around line 341-379: Extract the duplicated exporter serialization logic in
grpc.py by introducing a shared helper around model_dump_json and model_dump,
reusing the same exclude_fields construction and _visible_exporters() iteration
in both methods. Keep the helper centered on the unique symbols model_dump_json,
model_dump, and _visible_exporters so any future include_* field changes only
need to be updated in one place.
🪄 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: 1c80cb44-48e3-4a34-98ed-c3e495add5cc

📥 Commits

Reviewing files that changed from the base of the PR and between ededacb and 002364e.

⛔ Files ignored due to path filters (8)
  • controller/internal/protocol/jumpstarter/client/v1/client.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/client/v1/client_grpc.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/common.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/jumpstarter.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/jumpstarter_grpc.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/kubernetes.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/router.pb.go is excluded by !**/*.pb.go
  • controller/internal/protocol/jumpstarter/v1/router_grpc.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (35)
  • controller/Makefile
  • controller/api/v1alpha1/exporter_helpers.go
  • controller/api/v1alpha1/exporter_types.go
  • controller/api/v1alpha1/lease_helpers.go
  • controller/api/v1alpha1/lease_types.go
  • controller/api/v1alpha1/zz_generated.deepcopy.go
  • controller/buf.gen.yaml
  • controller/deploy/operator/config/crd/bases/jumpstarter.dev_exporteraccesspolicies.yaml
  • controller/deploy/operator/config/crd/bases/jumpstarter.dev_exporters.yaml
  • controller/deploy/operator/config/crd/bases/jumpstarter.dev_leases.yaml
  • controller/internal/controller/lease_controller.go
  • controller/internal/controller/lease_controller_test.go
  • protocol/proto/jumpstarter/client/v1/client.proto
  • python/Makefile
  • python/buf.gen.yaml
  • python/packages/jumpstarter-cli/jumpstarter_cli/create.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/create_test.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get.py
  • python/packages/jumpstarter-cli/jumpstarter_cli/get_test.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-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.pyi
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py
  • python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.pyi
  • python/packages/jumpstarter/jumpstarter/client/grpc.py
  • python/packages/jumpstarter/jumpstarter/client/grpc_test.py
  • python/packages/jumpstarter/jumpstarter/config/client.py
  • python/packages/jumpstarter/jumpstarter/config/client_config_test.py

Comment thread controller/internal/controller/lease_controller_test.go
Comment thread controller/internal/controller/lease_controller.go
Comment thread protocol/proto/jumpstarter/client/v1/client.proto Outdated
- proto: change Exporter.enabled to optional bool for backward compat
  When an old server omits the field, clients now correctly treat
  exporters as enabled (default true) instead of disabled (proto3
  bool default false). Matches existing pattern: optional bool
  only_active, optional bool release_lease.

- controller: add explicit AllDisabled status when all selector-matching
  exporters are disabled, instead of falling through to the misleading
  NoAccess/0-exporters message.

- test: add Unsatisfiable condition assertion to the all-disabled test
  case, matching the pattern used in other lease reconciliation tests.
string status_message = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
// Whether the exporter is enabled for lease assignment.
// When false, the controller will not assign new leases to this exporter.
bool enabled = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Claude AI analysis

@bennyz is right — this should be optional bool for backward compatibility.

In proto3, a non-optional bool has an implicit default of false with no presence tracking. When an old server (that doesn't know about the enabled field) sends an Exporter message to a new client, the field will be absent on the wire and the client deserializes it as false — making every exporter from an old server appear disabled.

The generated Go getter confirms this (client.pb.go):

func (x *Exporter) GetEnabled() bool {
    if x != nil {
        return x.Enabled
    }
    return false  // wrong default for compat!
}

With optional bool enabled = 6, proto3 generates presence-tracking, so client code can distinguish "server didn't send this field" (old server -> treat as enabled) from "server explicitly sent false" (disabled).

The project already follows this pattern:

  • optional bool only_active = 5 in ListLeasesRequest (this file, line 207)
  • optional bool release_lease = 3 in jumpstarter.proto
  • The K8s CRD side already uses *bool with nil-means-true in exporter_helpers.go:15-16

allow_disabled (field 14) is fine as plain bool — its default of false is the correct backward-compatible behavior.

Fix: change this line to:

optional bool enabled = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

Then update Go serialization in exporter_helpers.go:44 to use a pointer:

Enabled: proto.Bool(e.IsEnabled()),

And the Python client (grpc.py:112) to handle the optional:

enabled=data.enabled if data.HasField("enabled") else True,

Comment thread controller/internal/controller/lease_controller.go
Comment thread controller/internal/controller/lease_controller_test.go
@mangelajo mangelajo added this pull request to the merge queue Jul 8, 2026
Comment thread protocol/proto/jumpstarter/client/v1/client.proto Outdated
Merged via the queue into main with commit d46e91a Jul 8, 2026
30 checks passed
@mangelajo mangelajo deleted the feat/exporter-enabled-field branch July 8, 2026 15:59
@jumpstarter-backport-bot

Copy link
Copy Markdown

Backport failed for release-0.9, because it was unable to cherry-pick the commit(s).

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin release-0.9
git worktree add -d .worktree/backport-863-to-release-0.9 origin/release-0.9
cd .worktree/backport-863-to-release-0.9
git switch --create backport-863-to-release-0.9
git cherry-pick -x d46e91a777ecbb988ef8e5284487e280b1574c10

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.

3 participants